赞
踩
补充:ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用者在程序中只需要调用ODBC API,由 ODBC 驱动程序将调用转换成为对特定的数据库的调用请求。
ava.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
@Test public void testConnection1() throws SQLException { Driver driver = new com.mysql.jdbc.Driver(); //url:http:localhost:8080/gmall/keyboard.hpg //jdbc:mysql:协议 //localhost:ip协议 //3306:默认mysql的端口号 //test:test数据库 String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8"; //?characterEncoding=utf8:设置字符格式 //封装用户名和密码 Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password","123456"); Connection conn = driver.connect(url,info); System.out.println(conn); }
@Test
public void testConnection2() throws Exception{
//使用反射
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)clazz.newInstance();
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","123456");
Connection conn = driver.connect(url,info);
System.out.println(conn);
}
@Test public void testConnection3() throws Exception{ //1.获取Driver实现类的对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver)clazz.newInstance(); String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8"; String user = "root"; String password = "123456"; //2.注册驱动 DriverManager.registerDriver(driver); //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); }
@Test public void testConnection4() throws Exception{ //1.提供基本信息 String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8"; String user = "root"; String password = "123456"; //2.加载Driver //连接MySQL数据库时 加载Driver这句代码也可以省略 Class.forName("com.mysql.jdbc.Driver"); /*在MySQL的Driver类中,声明了 static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } 加载时自动注册了驱动 */ //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); }
@Test public void testConnection5() throws Exception{ //1.读取配置文件的信息 InputStream rs = Connection.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties pro = new Properties(); pro.load(rs); String user = pro.getProperty("user"); String url = pro.getProperty("url"); String password = pro.getProperty("password"); String driverClass = pro.getProperty("driverClass"); //2.加载Driver Class.forName(driverClass); //3.连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); }
数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
增:
@Test public void testInsert() throws Exception{ //连接数据库 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driverClass = pros.getProperty("driverClass"); Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); //预编译sql语句,返回PreparedStatement的实例 String sql = "insert into customers(name,email,birth)values(?,?,?)"; PreparedStatement pre = conn.prepareStatement(sql); pre.setString(1,"哪吒"); pre.setString(2,"nazha@163.com"); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); java.util.Date parse = simpleDateFormat.parse("2000-10-08"); pre.setDate(3,new Date(parse.getTime())); //执行操作 pre.execute(); //关闭资源 pre.close(); conn.close(); }
通用增删改
连接数据库关闭资源封装在JDBCutils.java内
public class JDBCutils { public static Connection getConnection() throws Exception{ //连接数据库 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driverClass = pros.getProperty("driverClass"); Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); return conn; } public static void closeResource(Connection con,Statement pre){ try { if(con != null) con.close(); if(pre != null) pre.close(); } catch (SQLException e) { e.printStackTrace(); } } }
//通用增删改 public void Update(String sql,Object ...args){ Connection conn = null; PreparedStatement pre = null; try{ //连接数据库 conn = JDBCutils.getConnection(); pre = conn.prepareStatement(sql); //填充占位符 for(int i = 0;i < args.length;i++){ pre.setObject(i+1,args[i]); } //执行操作 pre.execute(); }catch (Exception e){ e.printStackTrace(); }finally { //关闭资源 JDBCutils.closeResource(conn,pre); } }
测试:
public void UpdateTest(){
String sql = "update customers set name = ? where id = ?";
Update(sql,"Crown","19");
}
@Test public void testQuery1() throws Exception{ Connection conn = JDBCutils.getConnection(); String sql = "select name,email,birth from customers where id = ?"; PreparedStatement pre = conn.prepareStatement(sql); pre.setObject(1,1); //返回结果 ResultSet resultSet = pre.executeQuery(); if(resultSet.next()){//判断是否有下一个并指针后移 String name = resultSet.getString(1); String email = resultSet.getString(2); Date birth = resultSet.getDate(3); Customers customers = new Customers(name, email, birth); System.out.println(customers); } }
ORM编程思想
一个数据表对应一个java类,表中的一条记录对应java类的一个对象,表中的一个字段对应java的一个属性。
Java与SQL对应数据类型转换表
通用查询(针对一个表)
public Customers queryForCustomers(String sql, Object ...args) throws Exception{ Connection conn = JDBCutils.getConnection(); PreparedStatement pre = conn.prepareStatement(sql); for(int i=0;i< args.length;i++){ pre.setObject(i+1,args[i]); } ResultSet resultSet = pre.executeQuery(); //获取结果集的元数据 ResultSetMetaDate ResultSetMetaData metaData = resultSet.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = metaData.getColumnCount(); if(resultSet.next()){ Customers cust = new Customers(); //处理结果集一行数据中的每一个列 for(int j=0;j<columnCount;j++){ //获取列值 Object columValue = resultSet.getObject(j + 1); //获取每个列的列名 获取别名:getColumnLabel String columnName = metaData.getColumnName(j + 1); //将cust对象指定的columnName属性,赋值为columValue,通过反射 注意属性名应该与列名相同,可以通过别名实现 Field field = Customers.class.getDeclaredField(columnName); field.setAccessible(true); field.set(cust,columValue); } return cust; } JDBCutils.closeResources(conn,pre,resultSet); return null; } //测试: @Test public void testQuertCustomers() throws Exception{ String sql = "select id,name,birth,email from customers where id = ?"; Customers customers = queryForCustomers(sql,19); System.out.println(customers); }
针对不同表的查询,返回一条记录(一个对象)
使对象创建为动态
public <T> T queryForAllTable(Class<T> clazz,String sql, Object ...args) throws Exception{ Connection conn = JDBCutils.getConnection(); PreparedStatement pre = conn.prepareStatement(sql); for(int i=0;i< args.length;i++){ pre.setObject(i+1,args[i]); } ResultSet resultSet = pre.executeQuery(); //获取结果集的元数据 ResultSetMetaDate ResultSetMetaData metaData = resultSet.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = metaData.getColumnCount(); if(resultSet.next()){ T t = clazz.newInstance(); //处理结果集一行数据中的每一个列 for(int j=0;j<columnCount;j++){ //获取列值 Object columValue = resultSet.getObject(j + 1); //获取每个列的列名 String columnName = metaData.getColumnName(j + 1); //将cust对象指定的columnName属性,赋值为columValue,通过反射 Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(t,columValue); } return t; } JDBCutils.closeResources(conn,pre,resultSet); return null; }
针对不同表的查询,返回多条记录(多个对象)
使用List存储对象
public <T> List<T> QueryForAll(Class<T> clazz, String sql, Object ...args) throws Exception{ Connection conn = null; PreparedStatement pre = null; ResultSet resultSet = null; try { conn = JDBCutils.getConnection(); pre = conn.prepareStatement(sql); for(int i=0;i< args.length;i++){ pre.setObject(i+1,args[i]); } resultSet = pre.executeQuery(); //获取结果集的元数据 ResultSetMetaDate ResultSetMetaData metaData = resultSet.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = metaData.getColumnCount(); ArrayList<T> list = new ArrayList<>(); while(resultSet.next()){ T t = clazz.newInstance(); //处理结果集一行数据中的每一个列 for(int j=0;j<columnCount;j++){ //获取列值 Object columValue = resultSet.getObject(j + 1); //获取每个列的列名 String columnName = metaData.getColumnName(j + 1); //将cust对象指定的columnName属性,赋值为columValue,通过反射 Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(t,columValue); } list.add(t); } return list; } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResources(conn,pre,resultSet); } return null; }
PrepareStatement 预编译SQL语句
@Test public void testInsert() throws Exception{ Connection conn = JDBCutils.getConnection(); String sql = "insert into customers values(?,?,?,?,?)"; PreparedStatement pre = conn.prepareStatement(sql); pre.setObject(1,21); pre.setObject(2,"yun"); pre.setObject(3,"yun@123.com"); pre.setObject(4,"00-00-00"); FileInputStream fileInputStream = new FileInputStream(new File("lib/1.png")); pre.setBlob(5,fileInputStream); pre.execute(); JDBCutils.closeResource(conn,pre); }
@Test public void readTest() throws Exception{ InputStream is = null; FileOutputStream fos = null; Connection conn = JDBCutils.getConnection(); String sql = "select id,name,email,birth,photo from customers where id = ?"; PreparedStatement pre = conn.prepareStatement(sql); pre.setObject(1,16); ResultSet rs = pre.executeQuery(); if(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); Date birth = rs.getDate("birth"); Customers customers = new Customers(id, name, email, birth); System.out.println(customers); //使用文件的格式存储下来 Blob photo = rs.getBlob("photo"); is = photo.getBinaryStream(); fos = new FileOutputStream("zhuyin.jpg"); byte[] buffer = new byte[100000000]; int len; if((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } } JDBCutils.closeResources(conn,pre,rs); is.close(); fos.close(); }
如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。
update,delete本身就具有批量操作的效果
批量插入方式一
@Test
public void InsertTest() throws Exception{
Connection conn = JDBCutils.getConnection();
String sql = "insert into goods(name)values(?)";
PreparedStatement pre = conn.prepareStatement(sql);
for(int i = 1;i <= 2000;i++){
pre.setString(1,"name"+i);
pre.execute();
}
JDBCutils.closeResource(conn,pre);
}
}
批量插入方式二
mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
?rewriteBatchedStatements=true 写在配置文件的url后面
@Test public void InsertTest1() throws Exception{ Connection conn = JDBCutils.getConnection(); String sql = "insert into goods(name)values(?)"; PreparedStatement pre = conn.prepareStatement(sql); for(int i = 1;i <= 2000;i++){ pre.setString(1,"name"+i); //"攒"batch pre.addBatch(); if(i % 100 == 0) //执行batch pre.executeBatch(); //清空batch pre.clearBatch(); } JDBCutils.closeResource(conn,pre); } }
取消自动提交并手动提交
@Test public void InsertTest2() throws Exception{ Connection conn = JDBCutils.getConnection(); String sql = "insert into goods(name)values(?)"; PreparedStatement pre = conn.prepareStatement(sql); //设置不允许自动提交 conn.setAutoCommit(false); for(int i = 1;i <= 2000;i++){ pre.setString(1,"name"+i); //"攒"batch pre.addBatch(); if(i % 100 == 0) //执行batch pre.executeBatch(); //清空batch pre.clearBatch(); } //提交数据 conn.commit(); JDBCutils.closeResource(conn,pre); } }
保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务**回滚(rollback)**到最初状态。
JDBC程序中为了让多个 SQL 语句作为一个事务执行:
若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态 setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态。
例:AA转账给BB
public class TransactionTest { //通用增删改(事务版本) public void Update(Connection conn, String sql, Object ...args) throws Exception{ PreparedStatement pre = conn.prepareStatement(sql); for(int i = 0;i < args.length;i++){ pre.setObject(i+1,args[i]); } pre.execute(); JDBCutils.closeResource(null,pre); } @Test //事务演示例子 public void test(){ Connection connection = null; try { connection = JDBCutils.getConnection(); connection.setAutoCommit(false); String sql1 = "update user_table set balance = balance - 100 where user = ?"; Update(connection,sql1,"AA"); String sql2 = "update user_table set balance = balance + 100 where user = ?"; Update(connection,sql2,"BB"); connection.commit(); System.out.println("成功"); } catch (Exception e) { try { connection.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } }finally { try { connection.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } JDBCutils.closeResource(connection,null); } } }
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READ COMMITED 。
Mysql 支持 4 种事务隔离级别。Mysql 默认的事务隔离级别为: REPEATABLE READ。
每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别。
查看当前的隔离级别:
SELECT @@tx_isolation;
设置当前 mySQL 连接的隔离级别:
set transaction isolation level read committed;
设置数据库系统的全局的隔离级别:
set global transaction isolation level read committed;
补充操作:
创建mysql数据库用户:
create user tom identified by 'abc123';
授予权限
#授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码设为abc123.
grant all privileges on *.* to tom@'%' identified by 'abc123';
#给tom用户使用本地命令行方式,授予atguigudb这个库下的所有表的插删改查的权限。
grant select,insert,delete,update on atguigudb.* to tom@localhost identified by 'abc123';
类 BaseDAO.java:封装增删改查,查询等操作
public abstract class BaseDao { //通用增删改 public int update(Connection conn,String sql, Object ...args){ PreparedStatement pre = null; try{ //连接数据库 conn = JDBCutils.getConnection(); pre = conn.prepareStatement(sql); //填充占位符 for(int i = 0;i < args.length;i++){ pre.setObject(i+1,args[i]); } //执行操作 pre.execute(); }catch (Exception e){ e.printStackTrace(); }finally { //关闭资源 JDBCutils.closeResource(null,pre); } return 0; } //通用查询一个表 public <T> T getInstance(Connection conn,Class<T> clazz,String sql, Object ...args){ PreparedStatement pre = null; ResultSet resultSet = null; try { pre = conn.prepareStatement(sql); for(int i=0;i< args.length;i++){ pre.setObject(i+1,args[i]); } resultSet = pre.executeQuery(); //获取结果集的元数据 ResultSetMetaDate ResultSetMetaData metaData = resultSet.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = metaData.getColumnCount(); if(resultSet.next()){ T t = null; try { t = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } //处理结果集一行数据中的每一个列 for(int j=0;j<columnCount;j++){ //获取列值 Object columValue = resultSet.getObject(j + 1); //获取每个列的列名 String columnName = metaData.getColumnName(j + 1); //将cust对象指定的columnName属性,赋值为columValue,通过反射 Field field = null; try { field = clazz.getDeclaredField(columnName); } catch (Exception e) { e.printStackTrace(); } field.setAccessible(true); try { field.set(t,columValue); } catch (Exception e) { e.printStackTrace(); } } return t; } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCutils.closeResources(null,pre,resultSet); } return null; } //查询多条记录 public <T> List<T> getForList(Connection conn,Class<T> clazz, String sql, Object ...args){ PreparedStatement pre = null; ResultSet resultSet = null; try { conn = JDBCutils.getConnection(); pre = conn.prepareStatement(sql); for(int i=0;i< args.length;i++){ pre.setObject(i+1,args[i]); } resultSet = pre.executeQuery(); //获取结果集的元数据 ResultSetMetaDate ResultSetMetaData metaData = resultSet.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = metaData.getColumnCount(); ArrayList<T> list = new ArrayList<>(); while(resultSet.next()){ T t = clazz.newInstance(); //处理结果集一行数据中的每一个列 for(int j=0;j<columnCount;j++){ //获取列值 Object columValue = resultSet.getObject(j + 1); //获取每个列的列名 String columnName = metaData.getColumnName(j + 1); //将cust对象指定的columnName属性,赋值为columValue,通过反射 Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(t,columValue); } list.add(t); } return list; } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResources(null,pre,resultSet); } return null; } //查询特殊值 public <E> E getValue(Connection conn,String sql,Object ...args){ PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(sql); for(int i = 0;i < args.length;i++){ ps.setObject(i+1,args[i]); } rs = ps.executeQuery(); if(rs.next()){ return (E) rs.getObject(1); } } catch (SQLException e) { e.printStackTrace(); }finally { JDBCutils.closeResources(null,ps,rs); } return null; } }
抽象接口:CustomerDAO:定义各种功能
public interface CustomerDAO { //将cust对象添加到数据库中 void insert(Connection conn, Customers cust); //根据id删除表中一条记录 void delete(Connection conn,int id); //针对内存中的cust对象,去修改数据表中指定的记录 void update(Connection conn,Customers cust); //针对指定的id查询得到对应Customers对象 Customers getCutsomerByID(Connection conn,int id); //查询表中的所有记录构成的集合 List<Customers> getAll(Connection conn); //查询表有多少条记录 Long getCount(Connection conn); //返回数据表中最大的生日 Date getMaxBirth(Connection conn); }
类 CustomerDAOImpl:继承BaseDAO和CustomerDAO,功能的具体实现
public class CustomerDAOImpl extends BaseDao implements CustomerDAO{ @Override public void insert(Connection conn, Customers cust) { String sql = "insert into customers(id,name,email,birth) values(?,?,?,?)"; update(conn,sql,cust.getId(),cust.getName(),cust.getEmail(),cust.getBirth()); } @Override public void delete(Connection conn, int id) { String sql = "delete from customers where id = ?"; update(conn,sql,id); } @Override public void update(Connection conn, Customers cust) { String sql = "update customers set name = ?,email = ?,birth = ? where id = ?"; update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId()); } @Override public Customers getCutsomerByID(Connection conn, int id) { String sql = "select id,name,email,birth from customers where id = ?"; return getInstance(conn,Customers.class,sql,id); } @Override public List<Customers> getAll(Connection conn) { String sql = "select id,name,email,birth from customers"; return getForList(conn,Customers.class,sql); } @Override public Long getCount(Connection conn) { String sql = "select count(*) from customers"; return getValue(conn,sql); } @Override public Date getMaxBirth(Connection conn) { String sql = "select MAX(birth) from customers"; return getValue(conn,sql); } }
测试:
public class CustomerDAOImplTest { CustomerDAOImpl customerDAO = new CustomerDAOImpl(); @Test void testInsert() { Connection conn = null; try { conn = JDBCutils.getConnection(); Customers cust = new Customers(22, "abc", "abc@126.com", new Date(213131131331L)); customerDAO.insert(conn,cust); System.out.println("添加成功"); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testDelete() { Connection conn = null; try { conn = JDBCutils.getConnection(); customerDAO.delete(conn,22); System.out.println("删除成功"); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testUpdate() { Connection conn = null; try { conn = JDBCutils.getConnection(); Customers cust = new Customers(12, "黎明", "liming@111.com", new Date(21212112L)); customerDAO.update(conn,cust); System.out.println("更新成功"); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testGetCutsomerByID() { Connection conn = null; try { conn = JDBCutils.getConnection(); Customers cutsomerByID = customerDAO.getCutsomerByID(conn, 20); System.out.println(cutsomerByID); System.out.println("更新成功"); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testGetAll() { Connection conn = null; try { conn = JDBCutils.getConnection(); List<Customers> list = customerDAO.getAll(conn); list.forEach(System.out::println); System.out.println("更新成功"); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testGetCount() { Connection conn = null; try { conn = JDBCutils.getConnection(); Long count = customerDAO.getCount(conn); System.out.println(count); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } @Test void testGetMaxBirth() { Connection conn = null; try { conn = JDBCutils.getConnection(); Date maxBirth = customerDAO.getMaxBirth(conn); System.out.println(maxBirth); } catch (Exception e) { e.printStackTrace(); }finally { JDBCutils.closeResource(conn,null); } } }
优化
既然已经定义为Customers数据表下的功能,就没有必要在BaseDAO中查询时将Customers.class作为参数之一。作出以下修改:将BaseDAO改为泛型类,并写一个方法:泛型获取泛型类型
方法名修改(类已经定义为泛型,则方法名不需要重复定义):
**对于每一次数据库连接,使用完后都得断开。**否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。(回忆:何为Java的内存泄漏?)
数据库连接池的基本思想:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池
DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。
注意:
- 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
- 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
@Test public void testGetConnection() throws Exception{ //获取c3p0数据库连接池 ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "com.mysql.jdbc.Driverr" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:mysql://localhost::3306/test" ); cpds.setUser("root"); cpds.setPassword("123456"); //设置初始时数据库池中的连接数 cpds.setInitialPoolSize(10); Connection conn = cpds.getConnection(); System.out.println(conn); //销毁c3p0数据库连接池 // DataSources.destroy(cpds); }
<?xml version="1.0" encoding="UTF-8" ?> <c3p0-config> <!-- This app is massive! --> <named-config name="helloc3p0"> <!-- 提供获取连接的四个基本信息--> <property name="dricerClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///test</property> <property name="user">root</property> <property name="password">123456</property> <!-- 进行数据库连接池管理的基本信息--> <!--当数据库连接池的连接数不够时,c3p0一次性向数据库服务器申请的连接数 --> <property name="acquireIncrement">5</property> <!-- c3p0数据库连接池中初始化时的连接数--> <property name="initialPoolSize">10</property> <!-- c3p0数据库连接池维护的最少连接数 --> <property name="minPoolSize">10</property> <!-- c3p0数据库连接池维护的最多连接数--> <property name="maxPoolSize">100</property> <!--c3p0数据库连接池最多维护的Statement的个数 --> <property name="maxStatements">50</property> <!--每个连接中最多使用的Statement的个数 --> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
//方式二:使用配置文件 xml
@Test
public void testGetConnection1() throws Exception{
ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
Connection conn = cpds.getConnection();
System.out.println(conn);
}
使用配置文件读入
创建druid.properties
jdbcUrl=jdbc:mysql:///test
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
@Test
public void getConnection() throws Exception{
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
DataSource dataSource = DruidDataSourceFactory.createDataSource(pros);
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
@Test
public void test() throws Exception{
QueryRunner runner = new QueryRunner();
Connection conn = JDBCutils.getConnection();
String sql = "insert into customers(name,email,birth) values(?,?,?)";
int insertCount = runner.update(conn, sql, "蔡徐坤", "caixukun@123.com", "1997-02-13");
System.out.println("添加了" + insertCount + "条记录");
JDBCutils.closeResource(conn,null);
}
@Test //查询1:查询一条记录 BeanHandler public void Query1() throws Exception { QueryRunner runner = new QueryRunner(); Connection conn = JDBCutils.getConnection(); String sql = "select name,email,birth from customers where id = ?"; //BeanHander:是ResultSetHandler接口的实现类,用于封装表中的一条记录 BeanHandler<Customers> rsh = new BeanHandler<>(Customers.class); //query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) Customers cust = runner.query(conn, sql, rsh, 21); System.out.println(cust); JDBCutils.closeResource(conn,null); } @Test //查询1:查询一条记录 MapHandler public void Query3() throws Exception{ QueryRunner runner = new QueryRunner(); Connection conn = JDBCutils.getConnection(); String sql = "select name,email,birth from customers where id = ?"; //MapHander:是ResultSetHandler接口的实现类,对应表中的一条记录,将字段及相应字段的值作为map中的key和value MapHandler handler = new MapHandler(); Map<String, Object> map = runner.query(conn, sql, handler, 21); System.out.println(map); JDBCutils.closeResource(conn,null); }
@Test //查询2:查询多条记录BeanListHandler public void Query2() throws Exception { QueryRunner runner = new QueryRunner(); Connection conn = JDBCutils.getConnection(); String sql = "select name,email,birth from customers"; //BeanListHander:是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合 BeanListHandler<Customers> rsh = new BeanListHandler<>(Customers.class); //query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) List<Customers> cust = runner.query(conn, sql, rsh); cust.forEach(System.out::println); JDBCutils.closeResource(conn,null); } @Test //查询2:查询多条记录MapListHandler public void Query4() throws Exception{ QueryRunner runner = new QueryRunner(); Connection conn = JDBCutils.getConnection(); String sql = "select name,email,birth from customers"; //MapHander:是ResultSetHandler接口的实现类,对应表中的多条记录的集合,将字段及相应字段的值作为map中的key和value,将这些map添加到List中。 MapListHandler handler = new MapListHandler(); List<Map<String, Object>> list = runner.query(conn, sql, handler); list.forEach(System.out::println); JDBCutils.closeResource(conn,null); }
@Test
public void Query5() throws Exception{
QueryRunner runner = new QueryRunner();
Connection conn = JDBCutils.getConnection();
String sql = "select count(*) from customers";
ScalarHandler handler = new ScalarHandler();
Long count = (Long) runner.query(conn, sql, handler);
System.out.println(count);
JDBCutils.closeResource(conn,null);
}
@Test public void Query6() throws Exception { QueryRunner runner = new QueryRunner(); Connection conn = JDBCutils.getConnection(); String sql = "select id,name,email,birth from customers where id = ?"; ResultSetHandler<Customers> rsh = new ResultSetHandler<Customers>() { @Override public Customers handle(ResultSet resultSet) throws SQLException { if(resultSet.next()){ int id = resultSet.getInt("id"); String name = resultSet.getString("name"); String email = resultSet.getString("email"); Date birth = resultSet.getDate("birth"); return new Customers(id,name,email,birth); } return null; } }; Customers cust = runner.query(conn, sql, rsh, 21); System.out.println(cust); JDBCutils.closeResource(conn,null); }
DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。
DbUtils.close(conn);
/*
public static void close(Connection conn) throws SQLException {
if (conn != null) {
conn.close();
}
*/
DbUtils.closeQuietly(conn);
/* public static void closeQuietly(Connection conn) {
try {
close(conn);
} catch (SQLException var2) {
}
}*/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。