文章目录
前言
一、获取数据库连接(依次迭代)
方式一:获取Driver实现类对象
Driver driver=new com.mysql.cj.jdbc.Driver();
String url = "jdbc:mysql://localhost:3306/myblog";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "root");
Connection connect = driver.connect(url, properties);
System.out.println(connect);
方式二:使用反射
- 获取Driver实现类对象:使用反射
- 提供要连接的数据库
- 提供连接需要的用户名和密码
- 获取连接
//在下面的程序中不出现第三方的api,使得程序具有更好的可移植性
Class<?> clazz = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) clazz.getDeclaredConstructor().newInstance();
String url="jdbc:mysql://localhost:3306/myblog";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "root");
Connection connect = driver.connect(url, properties);
System.out.println(connect);
方式三:使用DriverManager替换Driver
- 获取Driver实现类对象
- 提供另外三个连接的基本信息
- 注册驱动
- 获取连接
Class<?> clazz = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) clazz.getDeclaredConstructor().newInstance();
String url="jdbc:mysql://localhost:3306/myblog";
String user="root";
String password="root";
DriverManager.registerDriver(driver);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
方式四:隐式注册驱动
- 提供另外三个连接的基本信息
- 加载Driver
- 获取连接
String url="jdbc:mysql://localhost:3306/myblog";
String user="root";
String password="root";
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
为什么可以省略–Class.forName(“com.mysql.cj.jdbc.Driver”);–操作呢?
在mysql的Driver实现类中,声明了如下的操作:
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
方式五:声明配置文件
- 读取配置文件中的4个基本信息
- 加载驱动
- 获取连接
将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
- 实现了数据与代码的分离。实现了解耦
- 如果需要修改配置文件信息,可以避免程序重新打包。
InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(is);
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driverClass = properties.getProperty("driverClass");
Class.forName(driverClass);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
jdbc.properties文件内容如下
二、使用
1.查询
a.查询某个表
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
connection = JDBCUtils.getConnection();
String sql ="select * from t_article where id = ?";
statement = connection.prepareStatement(sql);
statement.setObject(1, 27);
//执行,并返回结果集
resultSet = statement.executeQuery();
//处理结果集
if (resultSet.next()){
//判断结果集的下一条是否有数据,如果有数据返回true,并指针下移;如果返回false,指针不会下移。
int id = resultSet.getInt(1);
String title = resultSet.getString(2);
String author = resultSet.getString(3);
String sort = resultSet.getString(4);
Date date = resultSet.getDate(5);
int star = resultSet.getInt(6);
int comment = resultSet.getInt(7);
int visit = resultSet.getInt(8);
String content = resultSet.getString(9);
Article article = new Article(id,star,comment,visit,title,author,sort,content,date);
System.out.println(article);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement,resultSet);
}
b.通过反射生成方法
public Article queryForArticle(String sql,Object ... args) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = JDBCUtils.getDBCPConnection();
statement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
statement.setObject(i+1, args[i]);
}
resultSet = statement.executeQuery();
//获取结果集的元数据
ResultSetMetaData metaData = resultSet.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnCount = metaData.getColumnCount();
if (resultSet.next()){
Article article = new Article();
//处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
//获取列值
Object columnValue = resultSet.getObject(i + 1);
///获取每个列的列名
String columnName = metaData.getColumnName(i + 1);
//给Article对象指定的columnName属性,赋值为columnValue,通过反射
Field field = Article.class.getDeclaredField(columnName);
field.setAccessible(true);
field.set(article, columnValue);
}
return article;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(connection, statement,resultSet);
}
return null;
}
c.别名
针对于表的字段名与类的属性名不相同的情况:
- 必须声明sql时,使用类的属性名来命名字段的别名
- 使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName()获取列的别名。
说明:如果sql中没有给字段其别名,getColumnLabel()缺取的就是列名
public Comment commentQuery(String sql,Object ... args){
Connection connection =null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
connection = JDBCUtils.getDruidConnection();
statement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
statement.setObject(i+1,args[i]);
}
resultSet = statement.executeQuery();
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
if (resultSet.next()){
Comment comment = new Comment();
for (int i = 0; i < columnCount; i++) {
Object value = resultSet.getObject(i + 1);
//获取列的列名:getColumnName()---不推荐使用
// 获取列的别名:getColumnLabel()
// String columnName = rsmd.getColumnName(i + 1);
String columnName = rsmd.getColumnLabel(i + 1);
Field field = Comment.class.getDeclaredField(columnName);
field.setAccessible(true);
field.set(comment, value);
}
return comment;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection,statement,resultSet);
}
return null;
@Test
public void testCommentQuery(){
String sql="select id,article_id articleId,nickname nickName,content,time,star,diss dis from t_comment where id=?";
System.out.println(commentQuery(sql,25));
}
d.生成泛型方法
public <T> T getInstance(Class<T> clazz,String sql,Object ... args){
Connection connection =null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
connection = JDBCUtils.getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
statement.setObject(i+1,args[i]);
}
resultSet = statement.executeQuery();
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
if (resultSet.next()){
T t=clazz.getDeclaredConstructor().newInstance();
for (int i = 0; i < columnCount; i++) {
Object value = resultSet.getObject(i + 1);
String columnName = rsmd.getColumnLabel(i + 1);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, value);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection,statement,resultSet);
}
return null;
}
public <T> List<T> getForList(Class<T> clazz, String sql, Object ... args){
Connection connection =null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
connection = JDBCUtils.getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
statement.setObject(i+1,args[i]);
}
resultSet = statement.executeQuery();
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
ArrayList<T> list = new ArrayList<>();
while (resultSet.next()){
T t=clazz.getDeclaredConstructor().newInstance();
for (int i = 0; i < columnCount; i++) {
Object value = resultSet.getObject(i + 1);
String columnName = rsmd.getColumnLabel(i + 1);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, value);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection,statement,resultSet);
}
return null;
}
2.插入,更新,删除
单个修改
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
String sql = "update t_article set author = ? where id = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, "弟弟");
preparedStatement.setObject(2, 13);
preparedStatement.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, preparedStatement);
}
生成方法
public int update(String sql,Object ... args){
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
//String sql = "update t_article set author = ? where id = ?";
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
/*
ps,execute():
如果执行的是查询操作,有返回结果,则此方法返回true;
如果执行的是增、删、改操作,没有返回结果,则此方法返回false
* */
return preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, preparedStatement);
}
//'order'
return 0;
}
3.PreparedStatement对比Statement的优点
类型 | 大小(单位:字节) |
---|---|
TinyBlob | 最大255 |
Blob | 最大65K |
MediumBlob | 最大16M |
LongBlob | 最大4G |
操作Blob的数据
插入
Connection connection=null;
PreparedStatement statement=null;
try {
connection = JDBCUtils.getConnection();
String sql = "insert into dormitory(name,photo) values (?,?) ";
statement = connection.prepareStatement(sql);
statement.setObject(1, "刘鑫");
FileInputStream fis = new FileInputStream(new File("laida.png"));
statement.setBlob(2, fis);
statement.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement);
}
查询
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
InputStream is=null;
FileOutputStream fos=null;
try {
connection = JDBCUtils.getConnection();
String sql="select id,name,photo from dormitory where id=?";
statement = connection.prepareStatement(sql);
statement.setInt(1, 1);
resultSet = statement.executeQuery();
if (resultSet.next()){
int id = resultSet.getInt(1);
String name = resultSet.getString("name");
//将Blob类型的字段下载下来,以文件的方式保存在本地
Blob photo = resultSet.getBlob(3);
is = photo.getBinaryStream();
fos = new FileOutputStream("liuxin.png");
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer, 0, len);
}
System.out.println(id+","+name);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement,resultSet);
}
可以实现更高效的批量操作
update、delete本身就具有批量操作的效果。 此时的批量操作,主要指的是批量插入。使用PreparedStatement如何实现更高效的批量插入?
题目:向goods表中插入20000条数据CREATE TABLE goods(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(25));
方式一:使用Statement
Connection conn = JDBCUtils.getConnection( );
Statement st = conn.createStatement( );
for(int i = 1;i <= 20000;i++){
String sql = "insert into goods(name)values( ' name_" + i + "')";
st.execute(sql);
}
方式二:使用PreparedStatement
Connection connection=null;
PreparedStatement statement=null;
try {
connection= JDBCUtils.getConnection();
String sql="insert into dormitory(name) values (?)";
statement = connection.prepareStatement(sql);
for (int i = 0; i < 20000; i++) {
statement.setString(1,"name_"+i);
statement.execute();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement);
}
方式三
- addBatch()、executeBatch()、clearBatch()
- mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
- ?rewriteBatchedStatements=true写在配置文件的url后面
- 使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
Connection connection=null;
PreparedStatement statement=null;
try {
connection= JDBCUtils.getConnection();
String sql="insert into goods(name) values (?)";
statement = connection.prepareStatement(sql);
for (int i = 0; i < 20000; i++) {
statement.setString(1,"name_"+i);
//1."攒"sql
statement.addBatch();
if (i%500==0){
//执行batch
statement.executeBatch();
//清空batch
statement.clearBatch();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement);
}
方式四:事务
Connection connection=null;
PreparedStatement statement=null;
try {
connection= JDBCUtils.getConnection();
//设置不允许自动提交
connection.setAutoCommit(false);
String sql="insert into goods(name) values (?)";
statement = connection.prepareStatement(sql);
for (int i = 0; i <= 20000; i++) {
statement.setString(1,"name_"+i);
//1."攒"sql
statement.addBatch();
if (i%500==0){
//执行batch
statement.executeBatch();
//清空batch
statement.clearBatch();
}
}
connection.commit();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(connection, statement);
}
4.数据类型
Java与SQL对应数据类型转换表
项目 | Value |
---|---|
boolean | BIT |
byte | TINYINT |
short | SMALLINT |
int | INTEGER |
long | BIGINT |
String | CHAR,VARCHAR,LONGVARCHAR |
byte array | BINARY , VAR BINARY |
java.sql.Date | DATE |
java.sql.Time | TIME |
java.sql.Timestamp | TIMESTAMP |
四:事务
概念
- 一组逻辑操作单元(一个或多个DML操作(Data Manipulation Language)),使数据从一种状态变换到另一种状态。
- 事务处理的原则:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来,要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。
- 数据一旦提交,就不可回滚
- 哪些操作会导致数据的自动提交?
DDL操作(Data Definition Language)一旦执行,都会自动提交。
--------set autocommit = false 对DDL操作失效
DML默认情况下,一旦执行,就会自动提交。
--------我们可以通过set autocommit = false的方式取消DML操作的自动提交。
默认在关闭连接时,会自动的提交数据
事务的ACID属性
原子性( Atomicity )
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
—致性( consistency )
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
隔离性( lsolation )
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(Durability )
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
并发问题
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
脏读
对石两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段。之后,若T2回滚, T1读取的内容就是临时且无效的。
。
不可重复读
对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段。之后,T1再次读取同一个字段,值就不同了。
幻读
对于两个事务T1,T2,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行。之后,如果T1再次读取同一个表,就会多出几行。
- 数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。
- 一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
银行转账问题
问题再现
----------------------------------未考虑数据库事务情况下的转账操作----------------------------------
针对于数据表user_table来说:AA用户给BB用户转账10日
update user_table set balance = balance - 100 where user = ‘AA’
update user_table set balance = balance + 100 where user = ‘BB’
String sql1="update user_table set balance = balance - 100 where user = ?";
update(sql1, "AA");
System.out.println(10/0);
String sql2="update user_table set balance = balance + 100 where user = ?";
update(sql2, "BB");
System.out.println("转账成功");
通用的增删改操作(考虑上事务)
public int update(Connection connection,String sql,Object ... args){
PreparedStatement preparedStatement = null;
try {
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
return preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null, preparedStatement);
}
return 0;
}
通用的查询操作(考虑上事务),用于返回数据表中的一条记录
public <T> T getInstance(Connection connection,Class<T> clazz,String sql,Object ... args){
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
statement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
statement.setObject(i+1,args[i]);
}
resultSet = statement.executeQuery();
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
if (resultSet.next()){
T t=clazz.getDeclaredConstructor().newInstance();
for (int i = 0; i < columnCount; i++) {
Object value = resultSet.getObject(i + 1);
String columnName = rsmd.getColumnLabel(i + 1);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, value);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null,statement,resultSet);
}
return null;
}
加入事务改进后
Connection connection = null;
try {
connection = JDBCUtils.getConnection();
//1.建立连接
connection.setAutoCommit(false);
String sql1="update user_table set balance = balance - 100 where user = ?";
update(connection,sql1, "AA");
System.out.println(10/0);
String sql2="update user_table set balance = balance + 100 where user = ?";
update(connection,sql2, "BB");
System.out.println("转账成功");
//2.提交操作
connection.commit();
} catch (Exception e) {
e.printStackTrace();
//3.回滚
assert connection != null;
connection.rollback();
} finally {
//4.修改其为自动提交数据,主要针对于使用数据库连接池的使用
assert connection != null;
connection.setAutoCommit(true);
JDBCUtils.closeResource(connection, null);
}
隔离级别
隔离级别 | 描述 |
---|---|
READ UNCOMMITTED(读未提交数据) | 允许事务读取未被其他事物提交的变更,脏读、不可重复读和幻读的问题都会出现 |
READ COMMITED(读已提交数据) | 只允许事务读取已经被其它事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然可能出现 |
REPEATABLE READ(可重复读) | 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期问,禁止其他事物对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题仍然存在。 |
SERIALIZABLE(串行化) | 确保事务可以从一个表中读取相同的行.在这个事务持续期间.禁止其他事务对该表执行插入.更新和删除操作.所有并发问题都可以避免,但性能十分低下. |
- Oracle支持的2种事务隔离级别:READ COMMITED, SERIALIZABLE。Oracle默认的事务隔离级别为:READ COMMITED。
- Mysql支持4种事务隔离级别。Mysql默认的事务隔离级别为: REPEATABLE READ。
Connection connection=null;
try {
connection = JDBCUtils.getConnection();
//获取当前连接的隔离级别
System.out.println(connection.getTransactionIsolation());
//设置数据库的隔离级别:
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
connection.setAutoCommit(false);
String sql="select id ,name,url,image from t_link where id =?";
System.out.println(getInstance(connection, Link.class, sql, 1));
} catch (Exception e) {
e.printStackTrace();
}
五:数据库连接池
CP30
设置驱动
//获取c3pO数据库连接池
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myblog?characterEncoding=utf-8&&rewriteBatchedStatements=true");
cpds.setUser("root");
cpds.setPassword("root");
//通过设置相关的参数,对数据库连接池进行管理:
//设置初始时数据库连接池中的连接数
cpds.setInitialPoolSize(10);
Connection connection = cpds.getConnection();
System.out.println(connection);
//销毁cp30数据库连接池
DataSources.destroy(cpds);
配置文件
ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
try {
System.out.println(cpds.getConnection());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 提供获取连接的4个基本信息-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/myblog?characterEncoding=utf-8</property>
<property name= "user">root</property>
<property name="password">root</property>
<!-- 进行数据库连接池管理的基本信息-->
<!-- 当数据库连接池中的连接数不够时,c3p日一次性向数据库服务器申请的连接数-->
<property name="acquireIncrement">5</property>
<!-- C3p0数据库连接池中初始化时的连接数-->
<property name="initialPoolSize">10</property>
<!-- c3p0数据库连接池维护的最少连接数-->
<property name= "minPoolSize">10</property>
<!-- c3p0数据库连接池维护的最多连接数-->
<property name= "maxPoolSize">1000</property>
<!-- c3p0数据库连接池最多维护的Statement的个数·-->
<property name= "maxStatements">50</property>
<!-- 每个连接中可以最多使用的Statement的个数-->
<property name= "maxStatementsPerConnection">2</property>
</named-config>
</c3p0-config>
封装到JDBCUtils
private static final ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
public static Connection getC3P0Connection() throws Exception {
return cpds.getConnection();
}
DBCP
设置驱动
//创建了DBCP的数据库连接池
BasicDataSource source=new BasicDataSource();
//设置基本信息
source.setDriverClassName("com.mysql.cj.jdbc.Driver");
source.setUrl("jdbc:mysql://localhost:3306/myblog?characterEncoding=utf-8&&rewriteBatchedStatements=true");
source.setUsername("root");
source.setPassword("root");
//还可以设置其他涉及数据库连接池管理的相关属性:
source.setInitialSize(10);
source.setMaxTotal(10);
Connection connection = source.getConnection();
System.out.println(connection);
配置文件
Properties properties =new Properties() ;
//1.
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties");
//2.
// FileInputStream fis = new FileInputStream("src/dbcp.properties");
properties.load(is);
BasicDataSource source = BasicDataSourceFactory.createDataSource(properties);
Connection connection = source.getConnection();
System.out.println(connection);
封装到JDBCUtils
private static BasicDataSource source;
public static Connection getDBCPConnection() throws Exception {
return source.getConnection();
}
static {
try {
Properties properties =new Properties() ;
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties");
properties.load(is);
source = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
Druid
使用
Properties properties =new Properties() ;
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
DataSource source = DruidDataSourceFactory.createDataSource(properties);
System.out.println(source.getConnection());
封装到JDBCUtils
private static DataSource dataSource;
public static Connection getDruidConnection() throws Exception {
return dataSource.getConnection();
}
static {
try {
Properties properties =new Properties() ;
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
六:Dbutils
commons-dbutils是Apache 组织提供的一个开源JDBC工具类库,封装了针对于数据库的增删改查操作
更新操作
Connection connection=null;
try {
QueryRunner runner = new QueryRunner();
connection = JDBCUtils.getDruidConnection();
String sql ="insert into t_link (name,url,image) values (?,?,?)" ;
int i = runner.update(connection, sql, "王宁", "www.baidu.com", "big");
System.out.println("添加了"+i+"条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(connection, null);
}
查询操作
BeanHandler
BeanHandler是ResultSetHandler接口的实现类,用于封装表中的一条记录。
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql = "select id,name,url,image from t_link where id = ?";
BeanHandler<Link> handler = new BeanHandler<>(Link.class);
System.out.println(runner.query(connection, sql, handler,2));
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql="select id,name,url,image from t_link where id > ?";
BeanListHandler<Link> listHandler = new BeanListHandler<>(Link.class);
List<Link> list = runner.query(connection, sql, listHandler, 2);
for (Link link : list) {
System.out.println(link);
}
MapHandler
MapHandler是ResultSetHandler接口的实现类,对应表中的一条记录(将字段及相应字段的值作为map中的key和value)。
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql="select id,name,url,image from t_link where id > ?";
MapHandler handler = new MapHandler();
Map<String, Object> query = runner.query(connection, sql, handler, 2);
System.out.println(query+"-----"+query.size());
MapListHandler
MapListHandler:是ResultSetHandler接口的实现类,对应表中的一条记录(将字段及相应字段的值作为map中的key和value)。
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql="select id,name,url,image from t_link where id > ?";
MapListHandler handler = new MapListHandler();
List<Map<String, Object>> query = runner.query(connection, sql, handler, 2);
System.out.println(query+"-----"+query.size());
ScalarHandler
用于查询特殊值
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql="select count(*) from t_link ";
ScalarHandler<Long> handler = new ScalarHandler<>();
Long query = runner.query(connection, sql, handler);
System.out.println(query+"-----");
自定义
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtils.getDruidConnection();
String sql = "select id,name,url,image from t_link where id = ?";
ResultSetHandler<Link> handler = new ResultSetHandler<Link>() {
@Override
public Link handle(ResultSet resultSet) throws SQLException {
return new Link(5, "Z战士", "www", "small");
}
};
Link query = runner.query(connection, sql, handler, 6);
System.out.println(query+"-----");
关闭数据库连接操作
public static void closeUtilsResource(Connection connection, PreparedStatement statement, ResultSet resultSet){
DbUtils.closeQuietly(resultSet);
DbUtils.closeQuietly(connection);
DbUtils.closeQuietly(statement);
}