兴趣爱好 Java java学习笔记(二十五) - JDBC 执笔 2022-07-31 2024-06-10 JDBC概述
介绍
作用:为访问不同的数据库提供了统一的接口
JDBC API是Java提供一套基于数据库操作的接口API
原理
 - JDBC/JDBC原理.png)
JDBC程序编写步骤
注册驱动
 - JDBC/mysql驱动jar包.png)
1 2 3 4 5 6 Driver driver = new Driver ();
获取连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 String url = "jdbc:mysql://localhost:3306/study" ;Properties properties = new Properties ();properties.setProperty("user" ,"root" ); properties.setProperty("password" ,"123456" ); Connection connect = driver.connect(url, properties);
执行DML语句(增删改查)
1 2 3 4 5 6 7 8 9 10 11 12 String sql = "delete from actor where id = 1" ;Statement statement = connect.createStatement();int rows = statement.executeUpdate(sql);System.out.println(rows > 0 ? "成功" : "失败" );
释放资源
1 2 3 statement.close(); connect.close();
连接数据库的方式
获取Driver实现类对象
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void connect01 () throws SQLException { Driver driver = new Driver (); String url = "jdbc:mysql://localhost:3306/study" ; Properties properties = new Properties (); properties.setProperty("user" ,"root" ); properties.setProperty("password" ,"123456" ); Connection connect = driver.connect(url, properties); System.out.println("方式1:" + connect); }
通过反射
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void connect02 () throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { Class<?> aClass = Class.forName("com.mysql.jdbc.Driver" ); Driver driver = (Driver) aClass.newInstance(); String url = "jdbc:mysql://localhost:3306/study" ; Properties properties = new Properties (); properties.setProperty("user" ,"root" ); properties.setProperty("password" ,"123456" ); Connection connect = driver.connect(url, properties); System.out.println("方式2:" + connect);
使用DriverManager 替代Driver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Test public void connect03 () throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { Class<?> aClass = Class.forName("com.mysql.jdbc.Driver" ); Driver driver = (Driver) aClass.newInstance(); String url = "jdbc:mysql://localhost:3306/study" ; String user = "root" ; String password = "123456" ; DriverManager.registerDriver(driver); Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第三种方式:" + connection); }
使用Class.forName 自动完成注册驱动
推荐使用
mysql驱动5.1.6可以无需Class.forName(“com.mysql.jdbc.Driver”);
从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName(),注册驱动而是自动调用驱动jar包下的META-INTF\services\java.sql.Driver文本中的类名去注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void connect04 () throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver" ); String url = "jdbc:mysql://localhost:3306/study" ; String user = "root" ; String password = "123456" ; Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第4种方式:" + connection); }
class.froName 和 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void connect05 () throws IOException, ClassNotFoundException, SQLException { Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第5种方式:" + connection); }
resultSet结果集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class ResultSet_ { public static void main (String[] args) throws IOException, ClassNotFoundException, SQLException { Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); String sql = "select * from actor" ; ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) { int id = resultSet.getInt(1 ); String name = resultSet.getString(2 ); String sex = resultSet.getString(3 ); Date date = resultSet.getDate(4 ); String phone = resultSet.getString(5 ); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date + "\t" + phone ); } resultSet.close(); statement.close(); connection.close(); } }
sql注入
Statement对象用于执行静态SQL语句并返回其生成的结果的对象
在连接建立后,需要对数据库进行访问,执行命名或是SQL语句可以通过 Statement[存在SQL注入]、PreparedStatement[预处理]、CallableStatement [存储过程]
Statement对象执行SQL语句,存在SQL注入风险
SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库
要防范SQL注入 ,只要用PreparedStatement(从Statement扩展而来)取代 Statement 就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class Statement_ { public static void main (String[] args) throws IOException, ClassNotFoundException, SQLException { Scanner scanner = new Scanner (System.in); System.out.print("请输入用户名:" ); String admin_name = scanner.nextLine(); System.out.print("请输入密码:" ); String admin_pwd = scanner.nextLine(); Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); String sql = "select * from admin where name = '" + admin_name + "' and pwd = '" + admin_pwd + "'" ; ResultSet resultSet = statement.executeQuery(sql); if (resultSet.next()) { System.out.println("登入成功..." ); } else { System.out.println("登入失败..." ); } resultSet.close(); statement.close(); connection.close(); } }
PreparedStatement 预处理
PreparedStatement 执行的SQL语句中的参数用问号?)来表示,调用PreparedStatement对象的setXxx()方法来设置这些参数. setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
调用executeQuery(),返回ResultSet 对象
调用executeUpdate():执行更新,包括增、删、修改
executeQuery() 执行查询操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class PreparedStatement_ { public static void main (String[] args) throws Exception { Scanner scanner = new Scanner (System.in); System.out.print("请输入用户名:" ); String admin_name = scanner.nextLine(); System.out.print("请输入密码:" ); String admin_pwd = scanner.nextLine(); Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); String sql = "select * from admin where name = ? and pwd = ?" ; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1 ,admin_name); preparedStatement.setString(2 ,admin_pwd); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { System.out.println("登入成功..." ); } else { System.out.println("登入失败..." ); } resultSet.close(); preparedStatement.close(); connection.close(); } }
executeUpdate() 执行DML操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public class PreparedStatementDML { public static void main (String[] args) throws Exception { Scanner scanner = new Scanner (System.in); System.out.print("请输入用户名:" ); String admin_name = scanner.nextLine(); Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); String sql = "delete from admin where name = ?" ; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1 ,admin_name); int i = preparedStatement.executeUpdate(); System.out.println(i > 0 ? "成功.." : "失败..." ); preparedStatement.close(); connection.close(); } }
JDBC API
事务
JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务 ,每执行一个SQL语句,如果执行成功,就会像数据库自动提交,而且不能回滚
JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务
调用Connection的setAutoCommit(false) 可以取消自动提交事务
在所有的SQL语句都执行成功后,调用Connection的commit()方法提交事务
在其中某个操作失败或者异常时,调用Connection的rollBack()方法回滚事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public class Transaction_ { @Test public void noTransaction () { Connection connection = null ; String sql = "update account set balance = balance - 100 where id = 1" ; String sql2 = "update account set balance = balance + 100 where id = 2" ; PreparedStatement preparedStatement = null ; try { connection = JDBCUtils.getConnection(); preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); int i = 1 / 0 ; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(null , connection, preparedStatement); } } @Test public void useTransaction () { Connection connection = null ; String sql = "update account set balance = balance - 100 where id = 1" ; String sql2 = "update account set balance = balance + 100 where id = 2" ; PreparedStatement preparedStatement = null ; try { connection = JDBCUtils.getConnection(); connection.setAutoCommit(false ); preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); connection.commit(); } catch (SQLException e) { System.out.println("执行发生了异常,撤销执行的sql..." ); try { connection.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { JDBCUtils.close(null , connection, preparedStatement); } } }
批处理
当需要成批插入或者更新记录时,可以采用Java的批量更新机制
如果要使用批处理功能,JDBC连接Mysql时,需要在url中添加参数?rewriteBatchedStatements=true
批处理通常和PreparedStatement一起搭配使用,可以减少编译次数,减少运行次数,提高效率
1 2 3 4 addBatch(); executeBatch(); clearnBatch();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public class Batch_ { @Test public void noBatch () throws SQLException { Connection connection = JDBCUtils.getConnection(); String sql = "insert into admin2 values(null, ?, ?)" ; PreparedStatement preparedStatement = connection.prepareStatement(sql); System.out.println("开始执行" ); long start = System.currentTimeMillis(); for (int i = 0 ; i < 5000 ; i++) { preparedStatement.setString(1 , "jack" + i); preparedStatement.setString(2 , "666" ); preparedStatement.executeUpdate(); } long end = System.currentTimeMillis(); System.out.println("传统耗时 = " + (end - start)); JDBCUtils.close(null , connection, preparedStatement); } @Test public void batch () throws SQLException { Connection connection = JDBCUtils.getConnection(); String sql = "insert into admin2 values(null, ?, ?)" ; PreparedStatement preparedStatement = connection.prepareStatement(sql); System.out.println("开始执行" ); long start = System.currentTimeMillis(); for (int i = 0 ; i < 5000 ; i++) { preparedStatement.setString(1 , "jack" + i); preparedStatement.setString(2 , "666" ); preparedStatement.addBatch(); if ((i + 1 ) % 1000 == 0 ) { preparedStatement.executeBatch(); preparedStatement.clearBatch(); } } long end = System.currentTimeMillis(); System.out.println("批量耗时 = " + (end - start)); JDBCUtils.close(null , connection, preparedStatement); } }
数据库连接池
概念
JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource是一个接口,通常由第三方实现
预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需要从“缓冲池”中取出一个,使用完毕后在放回去
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是从新建立一个
当应用程序相连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列
分类
C3P0
速度相对较慢,稳定性不错(hiberbate、spring)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public class C3P0_ { @Test public void testC3P0_01 () throws Exception { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource (); Properties properties = new Properties (); properties.load(new FileInputStream ("src\\mysql.properties" )); String user = properties.getProperty("user" ); String password = properties.getProperty("password" ); String url = properties.getProperty("url" ); String driver = properties.getProperty("driver" ); comboPooledDataSource.setDriverClass(driver); comboPooledDataSource.setJdbcUrl(url); comboPooledDataSource.setUser(user); comboPooledDataSource.setPassword(password); comboPooledDataSource.setInitialPoolSize(10 ); comboPooledDataSource.setMaxPoolSize(50 ); long start = System.currentTimeMillis(); for (int i = 0 ; i < 5000 ; i++) { Connection connection = comboPooledDataSource.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("c3p0 耗时 = " + (end - start)); } @Test public void testC3P0_02 () throws SQLException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource ("zb_study" ); long start = System.currentTimeMillis(); for (int i = 0 ; i < 500000 ; i++) { Connection connection = comboPooledDataSource.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("c3p0 第二种方式 耗时= " + (end-start)); } }
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <c3p0-config> <!-- c3p0连接池配置 --> <!-- 数据源名称代表连接池 --> <named-config name= "zb_study" > <!--默认是mysql数据库--> <!--驱动类--> <property name="driverClass" >com.mysql.jdbc.Driver</property> <!--url--> <property name="jdbcUrl" >jdbc:mysql: <!-- 数据库的用户名 默认值:null --> <property name="user" >root</property> <!-- 数据库的密码 默认值:null --> <property name="password" >123456 </property> <!--初始化连接数 取值要在minPoolSize和maxPoolSize之间(可包含,闭区间) 默认值:3 --> <property name="initialPoolSize" >5 </property> <!-- 最大连接数 (连接池中的连接数不能超过maxPoolSize最大连接数) 默认值:15 --> <property name="maxPoolSize" >50 </property> <!--最小连接数 默认值:3 --> <property name="minPoolSize" >10 </property> <!-- c3p0连接池中数据连接不够时(无空闲连接可用),一次增长的个数(增长不能超过maxPoolSize最大连接个数) 默认值:3 --> <property name="acquireIncrement" >5 </property> <!-- 连接的最大空闲时间,如果超过这个时间还没有被使用,就断开这个连接(设置为0 或负数,就永远都不会被断开) 单位:秒 默认值 :0 --> <property name="maxIdleTime" >600 </property> <!-- 从数据库获取新连接失败后重复尝试的次数。小于等于0 表示无限次 默认值: 30 --> <property name="acquireRetryAttempts" value="30" /> <!-- 两次连接的中间间隔时间(重新尝试的时间间隔) 单位:毫秒 默认值:1000 --> <property name="acquireRetryDelay" >1000 </property> <!-- 连接关闭时,是否将所有未提交的操作进行事务回滚 默认值:false --> <property name="autoCommitOnClose" >false </property> <!-- 当连接池用完时,客户端调用getConnection()后等待获取新连接的时间 单位:毫秒 默认值:0 如果值设为 0 ,将无限期等待,直到有空闲连接。 否则按照设置的值,超时将抛出SQLException异常 时间设置过小时会出现连接超时,这样会抛出SQLException异常,设置时间时需要小心,按照实际情况设置适当的值--> <property name="checkoutTimeout" >0 </property> <!-- 每隔多少秒检查所有连接池中的空闲连接 单位:秒 默认值:0 --> <property name="idleConnectionTestPeriod" >60 </property> <!-- 配置PreparedStatement缓存,设置连接池为数据源缓存的PreparedStatement的总数 为0 的时候不缓存,同时maxStatementsPerConnection的配置无效。 由于PreparedStatement属于单个Connection,所以这个数量应该根据应用中平均连接数乘以每个连接的平均PreparedStatement来计算--> <property name="maxStatements" >1000 </property> <!-- 每个对象可连接的最多命令对象数 --> <property name="maxStatementsPerConnection" >2 </property> </named-config> </c3p0-config>
DBCP
Proxool
BoneCP
Druid(德鲁伊)
是阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池(推荐使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Druid_ { @Test public void testDruid () throws Exception { Properties properties = new Properties (); properties.load(new FileInputStream ("src\\druid.properties" )); DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); long start = System.currentTimeMillis(); for (int i = 0 ; i < 500000 ; i++) { Connection connection = dataSource.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("druid 连接池 耗时 = " + (end - start)); } }
JDBCUtilsByDruid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class JDBCUtilsByDruid { private static DataSource ds; static { Properties properties = new Properties (); try { properties.load(new FileInputStream ("src\\druid.properties" )); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { throw new RuntimeException (e); } } public static Connection getConnection () { try { return ds.getConnection(); } catch (SQLException e) { throw new RuntimeException (e); } } public static void close (ResultSet resultSet, Statement statement, Connection connection) { try { if (resultSet != null ) { resultSet.close(); } if (statement != null ) { statement.close(); } if (connection != null ) { connection.close(); } } catch (SQLException e) { throw new RuntimeException (e); } } }
Apache-DButils工具类
commons-dbutils是 Apache组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。
DbUtils类
QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理
使用QueryRunner类实现查询
ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式
1 2 3 4 5 6 7 ArrayHandler ArrayListHandler BeanListHandler ColumnListHandler KeyedHandler(name) MapHandler MapListHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 public class DBUtils_USE { @Test public void testQueryMany () throws SQLException { Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner (); String sql = "select id,name from actor where id >= ?" ; List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler <>(Actor.class), 1 ); System.out.println("集合的信息" ); for (Actor actor : list) { System.out.println(actor); } JDBCUtilsByDruid.close(null ,null ,connection); } @Test public void testQuerySingle () throws SQLException { Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner (); String sql = "select * from actor where id = ?" ; Actor actor = queryRunner.query(connection, sql, new BeanHandler <>(Actor.class), 4 ); System.out.println(actor); JDBCUtilsByDruid.close(null , null , connection); } @Test public void testScalar () throws SQLException { Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner (); String sql = "select name from actor where id = ?" ; Object obj = queryRunner.query(connection, sql, new ScalarHandler <>(), 4 ); System.out.println(obj); } @Test public void testDml () throws SQLException { Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner (); String sql = "delete from actor where id = ?" ; int affectRows = queryRunner.update(connection, sql, 2 ); System.out.println(affectRows > 0 ? "执行成功" : "执行没有受影响到表" ); JDBCUtilsByDruid.close(null ,null ,connection); } }
表和JavaBean的类型映射关系
DAO
DAO:data access object数据访问对象
BasicDAO
这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作。
在BaiscDao的基础上,实现一张表对应一个Dao,更好的完成功能,比如 Customer表-Customer.java类(javabean)-CustomerDao.java
 - JDBC/分层设计.png)
案例
domain
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 public class Actor { private Integer id; private String name; private String sex; private String borndate; private String phone; public Actor () { } public Actor (Integer id, String name, String sex, String borndate, String phone) { this .id = id; this .name = name; this .sex = sex; this .borndate = borndate; this .phone = phone; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getSex () { return sex; } public void setSex (String sex) { this .sex = sex; } public String getBorndate () { return borndate; } public void setBorndate (String borndate) { this .borndate = borndate; } public String getPhone () { return phone; } public void setPhone (String phone) { this .phone = phone; } @Override public String toString () { return "\nActor{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + ", borndate=" + borndate + ", phone='" + phone + '\'' + '}' ; } }
DAO
BasicDAO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public class BasicDAO <T> { private QueryRunner qr = new QueryRunner (); public int update (String sql, Object... parameters) { Connection connection = null ; try { connection = JDBCUtilsByDruid.getConnection(); return qr.update(connection, sql, parameters); } catch (SQLException e) { throw new RuntimeException (e); } finally { JDBCUtilsByDruid.close(null , null , connection); } } public List<T> queryMultiply (String sql, Class<T> clazz, Object... parameters) { Connection connection = null ; try { connection = JDBCUtilsByDruid.getConnection(); return qr.query(connection, sql, new BeanListHandler <T>(clazz), parameters); } catch (SQLException e) { throw new RuntimeException (e); } finally { JDBCUtilsByDruid.close(null , null , connection); } } public T querySingle (String sql, Class<T> clazz, Object... parameters) { Connection connection = null ; try { connection = JDBCUtilsByDruid.getConnection(); return qr.query(connection, sql, new BeanHandler <T>(clazz), parameters); } catch (SQLException e) { throw new RuntimeException (e); } finally { JDBCUtilsByDruid.close(null , null , connection); } } public Object queryScalar (String sql, Object... parameters) { Connection connection = null ; try { connection = JDBCUtilsByDruid.getConnection(); return qr.query(connection, sql, new ScalarHandler <T>(), parameters); } catch (SQLException e) { throw new RuntimeException (e); } finally { JDBCUtilsByDruid.close(null , null , connection); } } }
ActorDAO
1 2 3 4 5 6 7 8 9 public class ActorDAO extends BasicDAO <Actor>{ }
TestDAO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public class TestDAO { @Test public void tesActorDAO () { ActorDAO actorDAO = new ActorDAO (); List<Actor> actors = actorDAO.queryMultiply("select * from actor where id > ?" , Actor.class, 1 ); System.out.println("==== 多行查询结果 ====" ); for (Actor actor : actors) { System.out.println(actor); } Actor actor = actorDAO.querySingle("select * from actor where id = ?" , Actor.class, 4 ); System.out.println("==== 单行查询结果 ====" ); System.out.println(actor); Object o = actorDAO.queryScalar("select name from actor where id = ?" , 4 ); System.out.println("==== 单行单列查询结果 ====" ); System.out.println(o); int rows = actorDAO.update("update actor set name = ? where id = ?" , "李白" , 4 ); System.out.println("==== dml操作结果 ====" ); System.out.println(rows > 0 ? "执行成功" : "执行没有影响" ); } @Test public void testGoodsDAO () { GoodsDAO goodsDAO = new GoodsDAO (); String sql = "insert into goods values(?, ?, ?)" ; int rows = goodsDAO.update(sql, 20 , "苹果手机" , 8000 ); System.out.println("==== dml操作结果 ====" ); System.out.println(rows > 0 ? "执行成功" : "执行没有影响" ); List<Goods> goods = goodsDAO.queryMultiply("select * from goods where id > ?" , Goods.class, 1 ); System.out.println("==== 多行查询结果 ====" ); for (Goods good :goods) { System.out.println(good); } Object o = goodsDAO.querySingle("select * from goods where id = ?" , Goods.class, 10 ); System.out.println("==== 单行查询结果 ====" ); System.out.println(o); Object o1 = goodsDAO.queryScalar("select goods_name from goods where id = ?" , 20 ); System.out.println(o1); } }