01、JDBC
1、引言
1.1、如何操作数据库
使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写SQL语句,点击执行,查看操作结果(结果集或受影响行数)。

1.2、实际如何操作数据库
在实际开发中,当用户的数据发生改变时,不可能通过客户端操作执行SQL语句,因为操作量过大,无法保证效率和正确性
2、JDBC (Java Database Connectivity)
2.1、什么是JDBC
JDBC (Java Database Connectivity) Java连接数据库的规范(标准),可以使用Java 语言连接数据库完成CRUD操作。
2.2、JDBC核心思想
Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类〈Driver数据库驱动)。

2.2.1、MySQL数据库驱动
mysql-connector-java-5.1.X适用于5.X版本
mysql-connector-java-8.0.X适用于8.X版本
jar包下载地址
链接:https://pan.xunlei.com/s/VMezQUzS4jFhrN4LyyniwXwBA1
提取码:nwrw
复制这段内容后打开手机迅雷App,查看更方便
2.2.2、JDBC API
JDBC是由多个接口和类进行功能实现。
| 类型 | 权限定名 | 简介 |
| class | java.sql.DriverManager | 管理多个数据库驱动类,提供了获取数据库连接的方法 |
| interface | java.sql.Connection | 代表一个数据库连接(当connection不是null时,表示已连接数据库) |
| interface | java.sql.Statement | 发送SQL语句到数据库工具 |
| interface | java.sql.ResultSet | 保存SQL查询语句的结果数据(结果集) |
| class | java.sql.SQLException | 处理数据库应用程序时所发生的异常 |
2.3、环境搭建
创建Java项目
在项目下新建lib文件夹,用于存放jar文件。
将mysql 驱动mysql-connector-java-5.1.X复制到项目的lib文件夹中。
选中lib文件夹右键Add as Libraay,点击OK。
3、JDBC开发步骤【重点】
3.1、注册驱动
使用 Class.forName("com.mysql.jdbc.Driver");手动加载字节码文件到JVM中。
class.forName ( " com.mysql.jdbc. Driver");//加载驱动
3.2、连接数据库
通过 DriverManager.getConnection(url,user,password)获取数据库连接对象
URL: jdbc:mysql://localhost:3306/mydb2
username: root
password: root
Connection conn = DriverManager. getConnection(" jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=utf8", "root", "1234");
URL(Uniform Resource Locator)统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成
测试是否链接数据库是否成功
Class.forName("com.mysql.jdbc.Driver");
String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
String passworld ="root";
String username = "root";
Connection connection = DriverManager.getConnection(url,passworld,username);
if (connection != null){
System.out.println("连接到数据库啦");
}else {
System.out.println("连接失败");
}
3.3、获取发送SQL的对象
通过 Connection对象获得Statement对象,用于对数据库进行通用访问。
Statement statement =conn.createStatement();
3.4、执行sQL语句
执行SQL语句并接收执行结果。
String sql ="INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)VALUES( 'JAVA_Le' ,'JAVA_Lecturer' , 4008,10808) "; int result = statement.executeUpdate(sql);//执行SQL语句并接收结果
注意:
在编写DML语句时,一定要注意字符串参数的符号是单引号'值'
DML语句:增删改时,返回受影响行数(int类型)。
DQL语句:查询时,返回结果数据(ResultSet结果集)。
测试添加成功后,返回的值
// 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获取连接 String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8"; String passworld ="root"; String username = "root"; Connection connection = DriverManager.getConnection(url,passworld,username); // 获取发送sql的对象 Statement statement = connection.createStatement(); // 执行sql语句 String sql = "INSERT INTO `t_jobs` (`JOB_ID`,`JOB_TITLE`,`MIN_SALARY`,`MAX_SALARY`) VALUE ('JAVA_Le','JAVA_Lecturer',250,9000)"; int i = statement.executeUpdate(sql); System.out.println("执行的结果" +i);
3.5、处理结果
接受处理操作结果。
if(result == 1){ System.out.println( " Success");
}
受影响行数:逻辑判断、方法返回。
查询结果集:迭代、依次获取。
3.6、释放资源
遵循先开后关原则,释放所使用到的资源对象。
statement.close();
conn.close();
3.7、综合案例
整合以上核心六步,实现向数据库表中插入—条数据。
// 1、注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2、获取连接 String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8"; String passworld ="root"; String username = "root"; Connection connection = DriverManager.getConnection(url,passworld,username); // 3、获取发送sql的对象 Statement statement = connection.createStatement(); // 4、执行sql语句 String sql = "INSERT INTO `t_jobs` (`JOB_ID`,`JOB_TITLE`,`MIN_SALARY`,`MAX_SALARY`) VALUE ('JAVA_Les','JAVA_Lecturer',250,9000)"; int i = statement.executeUpdate(sql); // 5、处理结果 if (i == 1){ System.out.println("Success"); } // 6、释放资源 statement.close(); connection.close();
4、ResultSet(结果集)
在执行查询SQL后,存放查询到的结果集数据。
4.1、接收结果集
ResultSet rs = statement.executeQuery(sql);
ResultSet rs= statement. executeQuery( "SELECT * FROM t_employees;" );
4.2、遍历 ResultSet中的数据
ResultSet以表(table)结构进行临时结果的存储,需要通过JDBC API将其中数据进行依次获取。
数据行指针︰初始位置在第一行数据前,每调用一次boolean next()方法Resultset的指针向下移动一行,结果为true,表示当前行有数据。
rs.getXxx(整数);代表根据列的编号顺序获得,从1开始
rs.getXxx(""列名");代表根据列名获得。
boolean next() throws SQLException //判断rs 结果集中下一行是否存在数据
4.2.1、遍历方法
int getInt(int columnIndex) throws SQLException//获得当前行第N列的int值 int getInt(String columnLabel) throws SQLException//获得当前行columnLabel列的int值
double getDouble(int columnIndex) throws SQLException //获得当前行第N列的double值 double getDouble(String columnLabel) throws SQLException //获得当前行columnLabel列的double值
String getString(int columnIndex) throws SQLException //获得当前行第N列的String值 String getString(String columnLabel) throws SQLException//获得当前行columnLabel列的String值
注意: 列的编号从1开始。
4.3、综合案例
对t_jobs表中的所有数据进行遍历。
4.3.1、根据列的名称获取
// 加载驱动 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8"; String user = "root"; String password = "root"; // 获取连接数据库对象 Connection connection = DriverManager.getConnection(url, user, password); // 获取执行sql对象 Statement statement = connection.createStatement(); String sql = "SELECT * FROM `t_jobs`"; //执行sql语句 ResultSet resultSet = statement.executeQuery(sql); // 处理结果集 while (resultSet.next()){ String job_id = resultSet.getString("JOB_ID"); String job_title = resultSet.getString("JOB_TITLE"); String min_salary = resultSet.getString("MIN_SALARY"); String max_salary = resultSet.getString("MAX_SALARY"); System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary); } // 释放资源 resultSet.close(); statement.close(); connection.close();
4.3.2、根据列的编号获取数据
// 与上相同 // 处理结果集 while (resultSet.next()){ String job_id = resultSet.getString(1); String job_title = resultSet.getString(2); String min_salary = resultSet.getString(3); String max_salary = resultSet.getString(4); System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary); } // 释放资源
5、常见错误
java.lang.ClassNotFoundException: 找不到类(类名书写错误、没有导入jar包)
java.sqL.SQLException: 与sql语句相关的错误(约束错误、表名列名书写错误)建议:在客户端工具中测试SQL语句之后再粘贴在代码中
com.mysqL.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 原因:列值Sting类型没有加单引号
Duplicate entry '1' for key 'PRIMARY' 原因,主键值已存在或混乱,更改主键值或清空表
com.mysqL.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'password' in 原因: 可能输入的值的类型不对,确定是否插入的元素时对应的值的类型正确
6、综合案例【登录】
6.1、创建表
创建一张用户表User
id ,主键、自动增长。
用户名,字符串类型,唯一、非空。密码,字符串类型,非空
手机号码,字符串类型
插入1条测试语句
CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20) UNICODE NOT NULL, PASSWORD VARCHAR(20) NOT NULL, phone VARCHAR(11) )CHARSET=utf8 INSERT INTO users (`username`,`password`,`phone`)VALUE ('xiaohe','123456','18211510956')
6.2、实现登录
通过控制台用户输入用户名和密码。
用户输入的用户名和密码作为条件,编写查询SQL语句。
如果该用户存在,提示登录成功,反之提示失败。
Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名"); String username = scanner.nextLine(); System.out.println("请输入密码"); String password = scanner.nextLine(); // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8"; String user = "root"; String pword = "root"; // 获取连接数据库对象 Connection connection = DriverManager.getConnection(url, user, pword); // 获取执行sql对象 Statement statement = connection.createStatement(); String sql = "SELECT * FROM users WHERE username = '"+username+"' AND PASSWORD = '"+password+"'"; //执行sql ResultSet resultSet = statement.executeQuery(sql); // 处理结果集 if (resultSet.next()){ System.out.println("登录成功"); }else { System.out.println("登录失败"); } // 关闭资源 resultSet.close(); statement.close(); connection.close();
7、SQL注入问题
7.1、什么是SQL注入
用户输入的数据中有SQL关键字或语法并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一直得到正确的结果这种现象称为SQL注入。

7.2、如何避免SQL注入
由于编写的SQL语句是在用户输入数据,整合后再进行编译。所以为了避免SQL注入的问题,我们要使SQL语句在用户输入数据前就已进行编译成完整的 SQL语句,再进行填充数据。
8、PreparedStatement【重点】
PreparedStatement继承了Statement接口,执行SQL语句的方法无异。
8.1、PreparedStatement的应用
作用:
预编译SQL语句,效率高。
安全,避免SQL注入。
可以动态的填充数据,执行多个同构的SQL语句。
8.1.1、参数标记
//1.预编译SQL 语句 PreparedStatement pstmt = conn.prepareStatement("select ± from user where username=? and password=7");
注意:JDBC中的所有参数都由?符号占位,这被称为参数标记。在执行sQL语句之前,必须为每个参数提供值。
8.1.2、动态参数绑定
pstmt.setXxx(下标,值) 参数下标从1开始,为指定参数下标绑定值
//1.预编译SQL语句 PreparedStatement pstmt = conn.prepareStatement("select * from user where username=? and password=7");//2.为参数下标赋值 pstmt.setString(1, username); pstmt.setString(2, password);

9、封装工具类
在实际JDBC的使用中,存在着大量的重复代码:例如连接数据库、关闭数据库等这些操作 !
我们需要把传统的JDBC代码进行重构,抽取出通用的JDBC工具类! 以后连接任何数据库、释放资源都可以使用这个工具类。

9.1、重用性方案
封装获取连接、释放资源两个方法。
提供public static Connection getConnection()方法。
提供public static void closeAll(Connection conn , Statement sm , ResultSet rs){}方法。
9.1.1、重用工具类实现
package com.huiruan.JDBC; import java.sql.*; public class JDBCUtils { // 加载驱动 static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 获取连接 public static Connection getConnection(){ Connection connection = null; try { // 获取连接 String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8"; String passworld ="root"; String username = "root"; connection = DriverManager.getConnection(url, passworld, username); } catch (SQLException e) { e.printStackTrace(); } return connection; } // 关闭连接 public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){ try { if (resultSet != null){ resultSet.close(); } if (statement != null){ statement.close(); } if (connection != null){ connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
9.2、跨平台方案
定义public static final Properties prop = new Properties();//读取配置文件的Map
定义static{
// 首次使用工具类时,加载驱动
InputStream is = JDBCUtil.class.getResourceAsStream("路径");//通过复用本类自带流,读取jdbc.properties配置文件。
classPath = bin
prop.load(is); //通过prop对象将流中的配置信息分割成键值对
String driverName = prop.getProperty("driver");//通过driverName的键获取对应的值(com.mysqL.jdbc.Driver)
Class.forName(driverName);//加载驱动
}
9.2.1、跨平台工具类实现
在src目录下新建db.properties文件。

driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8 username=root passworld=root
工具类的封装。
package com.huiruan.JDBC2; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JDBCUtils { // 存储配置文件的map private static final Properties PROPERTIES = new Properties(); static { InputStream resourceAsStream = JDBCUtils.class.getResourceAsStream("/db.properties"); try { // 通过流,将配置文件内容加载到properties集合 PROPERTIES.load(resourceAsStream); String driver = PROPERTIES.getProperty("driver"); Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection(){ Connection connection = null; try { String url = PROPERTIES.getProperty("url"); String username = PROPERTIES.getProperty("username"); String passworld = PROPERTIES.getProperty("passworld"); connection = DriverManager.getConnection(url, username, passworld); } catch (SQLException e) { e.printStackTrace(); } return connection; } public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){ try { if (resultSet != null){ resultSet.close(); } if (statement != null){ statement.close(); } if (connection != null){ connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
10、ORM
ORM(object Relational Mapping)。
从数据库查询到的结果集(ResultSet)在进行遍历时,逐行遍历,取出的都是零散的数据。在实际应用开发中,我们需要将零散的数据进行封装整理。
10.1、实体类(entity):零散数据的载体
一行数据中,多个零散的数据进行整理。
通过entity的规则对表中的数据进行对象的封装。
表名=类名;列名=属性名;提供各个属性的get、set方法。
提供无参构造方法、(视情况添加有参构造)。
10.1.1、ORM应用
entity实体类
package com.huiruan.JDBC2; public class T_Jobs { private String job_id; private String job_title; private String min_salary; private String max_salary; public T_Jobs() { } public T_Jobs(String job_id, String job_title, String min_salary, String max_salary) { this.job_id = job_id; this.job_title = job_title; this.min_salary = min_salary; this.max_salary = max_salary; } public String getJob_id() { return job_id; } public String getJob_title() { return job_title; } public String getMin_salary() { return min_salary; } public String getMax_salary() { return max_salary; } public void setJob_id(String job_id) { this.job_id = job_id; } public void setJob_title(String job_title) { this.job_title = job_title; } public void setMin_salary(String min_salary) { this.min_salary = min_salary; } public void setMax_salary(String max_salary) { this.max_salary = max_salary; } @Override public String toString() { return "T_Jobs{" + "job_id='" + job_id + '\'' + ", job_title='" + job_title + '\'' + ", min_salary='" + min_salary + '\'' + ", max_salary='" + max_salary + '\'' + '}'; } }
查询结果封装
package com.huiruan.JDBC2; import java.sql.*; public class TestJDBC { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCUtils.getConnection(); String sql = "SELECT * FROM t_jobs"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ String job_id = resultSet.getString("JOB_ID"); String job_title = resultSet.getString("JOB_TITLE"); String min_salary = resultSet.getString("MIN_SALARY"); String max_salary = resultSet.getString("MAX_SALARY"); T_Jobs t_jobs = new T_Jobs(); t_jobs.setJob_id(job_id); t_jobs.setJob_title(job_title); t_jobs.setMin_salary(min_salary); t_jobs.setMax_salary(max_salary); System.out.println(t_jobs); } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection, preparedStatement,resultSet); } } }
11、DAO数据访问对象(Data Access Object)
DAO 实现了业务逻辑与数据库访问相分离。
对同一张表的所有操作封装在XxxDaolmpl对象中。
根据增删改查的不同功能实现具体的方法(insert、update、delete、select、selectAll)

11.1、创建数据库
# 创建—张表Person,有以下列: CREATE TABLE Person( # id: INT,主键,自动增长 id INT PRIMARY KEY AUTO_INCREMENT, # NAME: VARCHAR(20)非空 NAME VARCHAR(20) NOT NULL, # age: int非空 age INT NOT NULL, # bornDate:DATE bornDate DATE, # email:字符串 email VARCHAR(20), # address:字符串 address VARCHAR(20) )CHARSET=utf8;
11.2、封装实体类
创建entity实体类Person,编写属性私有化,构造方法,get/set方法。
package com.huiruan.person; import java.util.Date; public class Person { private int id; private String name; private int age; private Date bornDate; private String email; private String address; public Person() { } public Person(String name, int age, Date bornDate, String email, String address) { this.name = name; this.age = age; this.bornDate = bornDate; this.email = email; this.address = address; } public Person(int id, String name, int age, Date bornDate, String email, String address) { this.id = id; this.name = name; this.age = age; this.bornDate = bornDate; this.email = email; this.address = address; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public Date getBornDate() { return bornDate; } public String getEmail() { return email; } public String getAddress() { return address; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setBornDate(Date bornDate) { this.bornDate = bornDate; } public void setEmail(String email) { this.email = email; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", bornDate=" + bornDate + ", email='" + email + '\'' + ", address='" + address + '\'' + '}'; } }
11.3、编写Daolmpl类
编写Daolmpl类,提供增删改查方法,使用JDBC 开发步骤,完成功能。
package com.huiruan.person; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * 增、删、改、查单个、查所有 * 只做数据库访问操作!不参与逻辑判断 * 数据库一张表的访问的操作复用! */ public class PersonDaoImpl { // 新增 public int insert(Person person) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCUtils.getConnection(); String sql = "INSERT INTO `person` (`NAME`,`age`,`bornDate`,`email`,`address`)VALUE(?,?,?,?,?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, person.getName()); preparedStatement.setInt(2, person.getAge()); preparedStatement.setDate(3, DataUtils.utildateToSqldate(person.getBornDate())); preparedStatement.setString(4, person.getEmail()); preparedStatement.setString(5, person.getAddress()); int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection, preparedStatement, null); } return 0; } // 删除 public int delete(int id) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCUtils.getConnection(); String sql = "DELETE FROM `person` WHERE id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,id); int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.closeAll(connection,preparedStatement,null); } return 0; } // 修改 public int update(Person person) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCUtils.getConnection(); String sql = "UPDATE `person` SET `NAME` = ?,`age`=?,`bornDate`=?,`email`=?,`address`=? WHERE id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,person.getName()); preparedStatement.setInt(2,person.getAge()); preparedStatement.setDate(3,DataUtils.utildateToSqldate(person.getBornDate())); preparedStatement.setString(4,person.getEmail()); preparedStatement.setString(5,person.getAddress()); preparedStatement.setInt(6,person.getId()); int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection,preparedStatement,null); } return 0; } // 查单个 public Person seleteOne(int id) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCUtils.getConnection(); String sql = "SELECT `id`,`NAME`,`age`,`bornDate`,`email`,`address` FROM `person` WHERE `id` = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,id); resultSet = preparedStatement.executeQuery(); if (resultSet.next()){ int id1 = resultSet.getInt("id"); String name = resultSet.getString("NAME"); int age = resultSet.getInt("age"); Date bornDate = resultSet.getDate("bornDate"); String email = resultSet.getString("email"); String address = resultSet.getString("address"); Person person = new Person(id1,name,age,bornDate,email,address); return person; } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection,preparedStatement,resultSet); } return null; } // 查所有 public List<Person> seleteAll() { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCUtils.getConnection(); String sql = "SELECT `id`,`NAME`,`age`,`bornDate`,`email`,`address` FROM `person`"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); ArrayList<Person> personArrayList = new ArrayList<>(); while (resultSet.next()){ int id1 = resultSet.getInt("id"); String name = resultSet.getString("NAME"); int age = resultSet.getInt("age"); Date bornDate = resultSet.getDate("bornDate"); String email = resultSet.getString("email"); String address = resultSet.getString("address"); Person person = new Person(id1,name,age,bornDate,email,address); personArrayList.add(person); } return personArrayList; } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection,preparedStatement,resultSet); } return null; } }
12、Date工具类
现有问题:
数据库存储的数据类型为java.sqlL.Date。
而我们Java应用层存储日期类型为java.util.Date。
当我们用Java应用程序插入带有日期的数据到数据库中时,需要进行转换。
12.1、java.util.Date
Java语言常规应用层面的日期类型,可以通过字符串创建对应的时间对象。
无法直接通过JDBC插入到数据库。
12.2、java.sql.Date
不可以通过字符串创建对应的时间对象,只能通过毫秒值创建对象(1970年至今的毫秒值)。
可以直接通过JDBC插入到数据库。
12.3、SimpleDateFormat
格式化和解析日期的具体类。允许进行格式化(日期 -> 文本)、解析(文本 → 日期)和规范化。
12.3.1、SimpleDateFormat应用
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MN-dd" );//指定日期格式 java.util.Date date = sdf.parse(String dateStr); //将字符串解析成日期类型(java.util.Date) String dates = sdf.format(date);//将日期格式化成字符串
12.4、封装DateUtils工具类
package com.huiruan.person; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 时间工具 */ public class DataUtils { // 字符串转时间 public static java.util.Date strToDate(String str) { try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date parse = simpleDateFormat.parse(str); return parse; } catch (ParseException e) { e.printStackTrace(); } return null; } // 时间转字符串 public static String dateToStr(java.util.Date date) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String format = simpleDateFormat.format(date); return format; } // 时间转sql时间 public static java.sql.Date utildateToSqldate(java.util.Date date) { return new java.sql.Date(date.getTime()); } }
13、Service业务逻辑层
13.1、什么是业务
代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成。(软件所提供的一个功能都叫业务)。

13.2、Service开发流程

13.2.1、创建表
CREATE TABLE account( cardNo VARCHAR(20) PRIMARY KEY, PASSWORD VARCHAR(20) NOT NULL, NAME VARCHAR(20) NOT NULL, balance DOUBLE NOT NULL )CHARSET=utf8; INSERT INTO account(`cardNo`,`password`,`name`,`balance`)VALUE('6002','1234','xiaohe',1000); INSERT INTO account(`cardNo`,`password`,`name`,`balance`)VALUE('6003','1234','xiaoming',100)
13.2.2、实体类
package com.huiruan.account; public class Account { private String cardNo; private String password; private String name; private double balance; public Account() { } public Account(String cardNo, String password, String name, double balance) { this.cardNo = cardNo; this.password = password; this.name = name; this.balance = balance; } public String getCardNo() { return cardNo; } public void setCardNo(String cardNo) { this.cardNo = cardNo; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } @Override public String toString() { return "Account{" + "cardNo='" + cardNo + '\'' + ", password='" + password + '\'' + ", name='" + name + '\'' + ", balance=" + balance + '}'; } }
13.2.3、AccountDaoImpl
package com.huiruan.account; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class AccountDaoImpl { // 查询用户 public Account selectById(String id){ Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection= JDBCUtils.getConnection(); String sql = "SELECT * FROM account WHERE cardNo = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,id); resultSet = preparedStatement.executeQuery(); if (resultSet.next()){ String cardNo = resultSet.getString("cardNo"); String password = resultSet.getString("password"); String name = resultSet.getString("name"); double balance = resultSet.getDouble("balance"); Account account = new Account(cardNo, password, name, balance); return account; } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection,preparedStatement,resultSet); } return null; } // 更新用户 public int UpdateById(Account account){ Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCUtils.getConnection(); String sql = "UPDATE `account` SET `password`=?,`name`=?,`balance`=? WHERE `cardNo` = ? "; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,account.getPassword()); preparedStatement.setString(2,account.getName()); preparedStatement.setDouble(3,account.getBalance()); preparedStatement.setString(4,account.getCardNo()); int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(connection,preparedStatement,null); } return 0; } }
13.2.4、Service开发流程

13.2.5、AccountServiceImpl
package com.huiruan.account; public class AccountServiceImpl { public String transfer(String fromNo,String pwd,String toNo,double money){ String result = "转账失败"; AccountDaoImpl accountDao = new AccountDaoImpl(); try { // 查询fromNo用户是否存在 Account account = accountDao.selectById(fromNo); if (account == null){ throw new RuntimeException("---- fromNO用户不存在 -----"); } // 验证fromNo的密码是否正确 if (!account.getPassword().equals(pwd)){ throw new RuntimeException("-- 密码错误 --"); } // 验证余额是否充足 if (account.getBalance() < money){ throw new RuntimeException("-- 余额不足 --"); } // 查询toNo用户是否存在 Account account1 = accountDao.selectById(toNo); if (account1 == null){ throw new RuntimeException("-- toNo用户不存在 --"); } // 减少fromNo用户余额 account.setBalance(account.getBalance() - money); accountDao.UpdateById(account); int i = 10/0; // 添加tONo用户余额 account1.setBalance(account1.getBalance() + money); accountDao.UpdateById(account1); result = "转账成功"; } catch (RuntimeException e) { e.printStackTrace(); } finally { } return result; } }
14、事务
在JDBC 中,获得 Connection对象开始事务--提交或回滚--关闭连接。其事务策略是
conn.setAutoCommit(false);//true等价于1,false等价于0
conn.commit();//手动提交事务
conn.rollback();//手动回滚事务
14.1、service层控制事务
package com.huiruan.account; import java.sql.Connection; import java.sql.SQLException; public class AccountServiceImpl { public String transfer(String fromNo,String pwd,String toNo,double money){ String result = "转账失败"; AccountDaoImpl accountDao = new AccountDaoImpl(); Connection connection = null; try { // 创建数据库连接 connection = JDBCUtils.getConnection(); // 1、开启事务 connection.setAutoCommit(false); // 查询fromNo用户是否存在 Account account = accountDao.selectById(fromNo); if (account == null){ throw new RuntimeException("---- fromNO用户不存在 -----"); } // 验证fromNo的密码是否正确 if (!account.getPassword().equals(pwd)){ throw new RuntimeException("-- 密码错误 --"); } // 验证余额是否充足 if (account.getBalance() < money){ throw new RuntimeException("-- 余额不足 --"); } // 查询toNo用户是否存在 Account account1 = accountDao.selectById(toNo); if (account1 == null){ throw new RuntimeException("-- toNo用户不存在 --"); } // 减少fromNo用户余额 account.setBalance(account.getBalance() - money); accountDao.UpdateById(account); int i = 10/0; // 添加tONo用户余额 account1.setBalance(account1.getBalance() + money); accountDao.UpdateById(account1); connection.commit(); result = "转账成功"; } catch (Exception e) { e.printStackTrace(); try { System.out.println("出现异常,回滚"); connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { JDBCUtils.closeAll(connection,null,null); } return result; } }
以上代码没有控制到事务
14.2、解决方案
传递Connection
为了解决线程中Connection对象不同步的问题,可以将Connection对象通过service传递给各个DAO方法吗?
14.2.1、传递的问题
如果使用传递Connection,容易造成接口污染(BadSmell)。
定义接口是为了更容易更换实现,而将Connection定义在接口中,会造成污染当前接口。
14.3、解决方案
ThreadLocal
可以将整个线程中(单线程)中,存储一个共享值。
线程拥有一个类似Map的属性,键值对结构<ThreadLocal对象,值>。
14.4、ThreadLocal应用
一个线程共享同一个ThreadLocal,在整个流程中任一环节可以存值或取值。

14.4.1、参数绑定
在DBUtils中,将当前 Connection对象添加到ThreadLocal中。
package com.huiruan.account; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JDBCUtils { private static final Properties PROPERTIES = new Properties(); private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); static { try { InputStream resourceAsStream = JDBCUtils.class.getResourceAsStream("/db.properties"); PROPERTIES.load(resourceAsStream); Class.forName(PROPERTIES.getProperty("driver")); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 获取连接 public static Connection getConnection() { String url = PROPERTIES.getProperty("url"); String username = PROPERTIES.getProperty("username"); String passworld = PROPERTIES.getProperty("passworld"); // 通过threadLocal获取连接 Connection connection = threadLocal.get(); try { if (connection == null) { connection = DriverManager.getConnection(url, username, passworld); // 将connection保存到threadLocal中 threadLocal.set(connection); } } catch (SQLException e) { e.printStackTrace(); } return connection; } // 开启事务 public static void begin() { try { Connection connection = getConnection(); connection.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } // 提交事务 public static void commit() { Connection connection = null; try { connection = getConnection(); connection.commit(); } catch (SQLException e) { e.printStackTrace(); } finally { closeAll(connection, null, null); } } // 回滚事务 public static void rollback() { Connection connection = null; try { connection = getConnection(); connection.rollback(); } catch (SQLException e) { e.printStackTrace(); } finally { closeAll(connection,null,null); } } public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) { try { if (connection != null) { connection.close(); threadLocal.remove(); // 移除connection } if (statement != null) { statement.close(); } if (resultSet != null) { resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
dao的connection不能关闭
package com.huiruan.account; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class AccountDaoImpl { // 查询用户 public Account selectById(String id){ Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection= JDBCUtils.getConnection(); String sql = "SELECT * FROM account WHERE cardNo = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,id); resultSet = preparedStatement.executeQuery(); if (resultSet.next()){ String cardNo = resultSet.getString("cardNo"); String password = resultSet.getString("password"); String name = resultSet.getString("name"); double balance = resultSet.getDouble("balance"); Account account = new Account(cardNo, password, name, balance); return account; } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(null,preparedStatement,resultSet); } return null; } // 更新用户 public int UpdateById(Account account){ Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCUtils.getConnection(); String sql = "UPDATE `account` SET `password`=?,`name`=?,`balance`=? WHERE `cardNo` = ? "; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,account.getPassword()); preparedStatement.setString(2,account.getName()); preparedStatement.setDouble(3,account.getBalance()); preparedStatement.setString(4,account.getCardNo()); int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(null,preparedStatement,null); } return 0; } }
service开启事务
package com.huiruan.account; import java.sql.Connection; import java.sql.SQLException; public class AccountServiceImpl { public String transfer(String fromNo,String pwd,String toNo,double money){ String result = "转账失败"; AccountDaoImpl accountDao = new AccountDaoImpl(); try { JDBCUtils.begin(); // 查询fromNo用户是否存在 Account account = accountDao.selectById(fromNo); if (account == null){ throw new RuntimeException("---- fromNO用户不存在 -----"); } // 验证fromNo的密码是否正确 if (!account.getPassword().equals(pwd)){ throw new RuntimeException("-- 密码错误 --"); } // 验证余额是否充足 if (account.getBalance() < money){ throw new RuntimeException("-- 余额不足 --"); } // 查询toNo用户是否存在 Account account1 = accountDao.selectById(toNo); if (account1 == null){ throw new RuntimeException("-- toNo用户不存在 --"); } // 减少fromNo用户余额 account.setBalance(account.getBalance() - money); accountDao.UpdateById(account); // 添加tONo用户余额 account1.setBalance(account1.getBalance() + money); accountDao.UpdateById(account1); JDBCUtils.commit(); result = "转账成功"; } catch (Exception e) { e.printStackTrace(); JDBCUtils.rollback(); } return result; } }
15、三层架构
15.1、什么是三层
表示层
命名: XXXView
职责: 收集用户的数据和需求、展示数据。
业务逻辑层:
命名: XxXServicelmpl
职责: 数据加工处理、调用DAO完成业务实现、控制事务。
数据访问层:
命名: XXXDaolmpl
职责: 向业务层提供数据,将业务层加工后的数据同步到数据库。

15.2、三层架构项目搭建
utils 存放工具类(DBUtils)
entity 存放实体类(Person)
dao 存放DAO接口(PersonDao)
impl 存放DAO接口实现类(PersonDaolmpl)
service 存放service接口(PersonService)
impl 存放service接口实现类(PersonServicelmpl)
view 存放程序启动类(main)
程序设计时,考虑易修改、易扩展,为Service层和DAO层设计接口,便于未来更换实现类
15.3、项目目录

15.4、db.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8 username=root passworld=root
15.5、DbUtils
package com.huiruan.utils; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class DbUtils { private static final Properties PROPERTIES = new Properties(); private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>(); // 注册驱动 static { try { // 加载PersonProject资源 InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties"); PROPERTIES.load(resourceAsStream); Class.forName(PROPERTIES.getProperty("driver")); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** *获取连接 * @return connection */ public static Connection getConnection(){ // 获取连接 connection Connection connection = THREAD_LOCAL.get(); try { if (connection == null){ connection = DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("username"),PROPERTIES.getProperty("passworld")); THREAD_LOCAL.set(connection); } } catch (SQLException e) { e.printStackTrace(); } return connection; } /** * 关闭连接 * @param connection * @param statement * @param resultSet */ public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){ try { if (connection != null){ connection.close(); } if (statement != null){ statement.close(); } if (resultSet != null){ resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } } /** * 开启事务 */ public static void setAutoCommit(){ try { Connection connection = getConnection(); connection.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } /** * 提交事务 */ public static void commit(){ try { Connection connection = getConnection(); connection.commit(); } catch (SQLException e) { e.printStackTrace(); } } /** * 回滚事务 */ public static void rollback(){ try { Connection connection = getConnection(); connection.rollback(); } catch (SQLException e) { e.printStackTrace(); } } }
15.6、DateUtils
package com.huiruan.utils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateUtils { private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); /** * 字符串转时间 * @param str 字符串 * @return 时间 */ public static java.util.Date stringToDate(String str){ Date parse = null; try { parse = simpleDateFormat.parse(str); } catch (ParseException e) { e.printStackTrace(); } return parse; } /** * 时间转字符串 * @param date 时间 * @return 字符串 */ public static String dateToStr(java.util.Date date){ return simpleDateFormat.format(date); } /** * util时间转util时间 * @param date util时间 * @return util时间 */ public static java.sql.Date utilsdateToSqldate(java.util.Date date){ return new java.sql.Date(date.getTime()); } }
15.7、DaoUtils
package com.huiruan.utils; import com.huiruan.advanced.RowMapper; import java.sql.*; import java.util.ArrayList; import java.util.List; public class DaoUtils<T> { /** * 公共处理增、删、改的方法 * @param sql * @param args * @return */ public int commonsUpdate(String sql,Object... args){ Connection connection = null; PreparedStatement preparedStatement = null; try { connection = DbUtils.getConnection(); preparedStatement = connection.prepareStatement(sql); for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1,args[i]); } int i = preparedStatement.executeUpdate(); return i; } catch (SQLException e) { e.printStackTrace(); }finally { DbUtils.closeAll(null,preparedStatement,null); } return 0; } /** * 公共查询方法 * @param sql * @param rowMapper * @param args * @return */ public List<T> commonsSelect(String sql, RowMapper<T> rowMapper, Object... args){ Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; List<T> list = new ArrayList<>(); try { connection = DbUtils.getConnection(); preparedStatement = connection.prepareStatement(sql); if (args != null){ for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1,args[i]); } } resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ T t = rowMapper.getRow(resultSet); list.add(t); } return list; } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeAll(null,preparedStatement,resultSet); } return null; } }
15.8、RowMapper
package com.huiruan.advanced; import java.sql.ResultSet; public interface RowMapper<T> { public T getRow(ResultSet resultSet); }
15.9、PersonRowMapper
package com.huiruan.advanced.impl; import com.huiruan.advanced.RowMapper; import com.huiruan.entity.Person; import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; public class PersonRowMapper implements RowMapper<Person> { @Override public Person getRow(ResultSet resultSet) { Person person = null; try { int id = resultSet.getInt("id"); String name = resultSet.getString("name"); int age = resultSet.getInt("age"); Date bornDate = resultSet.getDate("bornDate"); String email = resultSet.getString("email"); String address = resultSet.getString("address"); person = new Person(id,name,age,bornDate,email,address); } catch (SQLException e) { e.printStackTrace(); } return person; } }
15.10、Person
package com.huiruan.entity; import java.util.Date; public class Person { private Integer id; private String name; private Integer age; private Date bornDate; private String email; private String address; public Person() { } public Person(Integer id, String name, Integer age, Date bornDate, String email, String address) { this.id = id; this.name = name; this.age = age; this.bornDate = bornDate; this.email = email; this.address = address; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBornDate() { return bornDate; } public void setBornDate(Date bornDate) { this.bornDate = bornDate; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", bornDate=" + bornDate + ", email='" + email + '\'' + ", address='" + address + '\'' + '}'; } }
15.11、PersonDao
package com.huiruan.dao; import com.huiruan.entity.Person; import java.util.List; public interface PersonDao { public int insert(Person person); public int update(Person person); public int delete(int id); public Person selectOne(int id); public List<Person> selectAll(); }
15.12、PersonDaoImpl
package com.huiruan.dao.impl; import com.huiruan.advanced.impl.PersonRowMapper; import com.huiruan.dao.PersonDao; import com.huiruan.entity.Person; import com.huiruan.utils.DaoUtils; import com.huiruan.utils.DateUtils; import com.huiruan.utils.DbUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.List; public class PersonDaoImpl implements PersonDao { private static DaoUtils<Person> daoUtils = new DaoUtils(); @Override public int insert(Person person) { String sql = "INSERT INTO person (`id`,`NAME`,`age`,`bornDate`,`email`,`address`) VALUE (?,?,?,?,?,?)"; Object[] obj = {person.getId(),person.getName(),person.getAge(),person.getBornDate(),person.getEmail(),person.getAddress()}; return daoUtils.commonsUpdate(sql,obj); } @Override public int update(Person person) { String sql = "UPDATE person SET `NAME` = ?, `age` = ?, `bornDate` = ?, `email` = ?, `address` = ? WHERE `id` = ?"; Object[] obj = {person.getName(),person.getAge(),DateUtils.utilsdateToSqldate(person.getBornDate()),person.getEmail(),person.getAddress(),person.getId()}; return daoUtils.commonsUpdate(sql,obj); } @Override public int delete(int id) { String sql = "delete from person where id = ?"; return daoUtils.commonsUpdate(sql, id); } @Override public Person selectOne(int id) { String sql = "select * from person where id = ?"; List<Person> people = daoUtils.commonsSelect(sql,new PersonRowMapper(),id); if (!people.isEmpty()){ return people.get(0); } return null; } @Override public List<Person> selectAll() { String sql = "select * from person"; List<Person> people = daoUtils.commonsSelect(sql, new PersonRowMapper()); return people; } }
16、Druid连接池
在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。
16.1 Druid连接池使用步骤
创建database.properties配置文件。
引入druid-1.1.5.jar文件。
引入mysql-connector-java-5.1.25-bin.jar文件。
引入commons-dbutils-1.7.jar文件。
16.1.1、database.properties配置文件
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8 username=root password=root #<!--初始化连接--> initialSize =10 #最大连接数量 maxActive=20 #<!--最小空闲连接--> minIdle=5 #<!--超时等待时间以毫秒为单位60000毫秒/1000等于60秒--> maxWait=5000
16.1.2、连接池工具类
package com.huiruan.utils; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DbUtils { // 声明连接池对象 private static DruidDataSource druidDataSource; static { // 实例化配置对象 try { Properties properties = new Properties(); InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties"); properties.load(resourceAsStream); DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); druidDataSource = (DruidDataSource) dataSource; } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接 * @return */ public static Connection getConnection(){ try { return druidDataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } /** * 获取连接池 * @return */ public static DruidDataSource getDruidDataSource(){ return druidDataSource; } }
17、Apache的DbUtils使用
Commons Dbutils,是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能勾简化JDBC应用程序的开发!同时,不会影响程序的性能。
17.1、DbUtils简介
DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用
对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。
对于数据表的DML操作,也变得很简单(只需要写SQL语句)。
17.1.1、DbUtils主要包含
ResultSetHandler接口:转换类型接口
BeanHandler类:实现类,把一条记录转换成对象
BeanListHandler类:实现类,把多条记录转换成List集合。
ScalarHandler类:实现类,适合获取一行一列的数据。
QueryRunner:执行sql语句的类
增、删、改:update();
查询:query();
17.2、DbUtils的使用步骤
导入jar包
mysql连接驱动jar包
druid-1.1.5.jar
database.properties配置文件
commons-dbutils-1.6.jar
17.2.1、db.properties
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8 username=root password=root #<!--初始化连接--> initialSize =10 #最大连接数量 maxActive=20 #<!--最小空闲连接--> minIdle=5 #<!--超时等待时间以毫秒为单位60000毫秒/1000等于60秒--> maxWait=5000
17.2.2、DbUtils工具类
package com.huiruan.utils; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DbUtils { // 声明连接池对象 private static DruidDataSource druidDataSource; static { // 实例化配置对象 try { Properties properties = new Properties(); InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties"); properties.load(resourceAsStream); DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); druidDataSource = (DruidDataSource) dataSource; } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接 * @return */ public static Connection getConnection(){ try { return druidDataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } /** * 获取连接池 * @return */ public static DruidDataSource getDruidDataSource(){ return druidDataSource; } }
17.2.3、User
package com.huiruan.entity; public class User { private Integer userId; private String username; private String password; private String address; private String phone; public User() { } public User(Integer userId, String username, String password, String address, String phone) { this.userId = userId; this.username = username; this.password = password; this.address = address; this.phone = phone; } public User(String username, String password, String address, String phone) { this.username = username; this.password = password; this.address = address; this.phone = phone; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "User{" + "userId=" + userId + ", username='" + username + '\'' + ", password='" + password + '\'' + ", address='" + address + '\'' + ", phone='" + phone + '\'' + '}'; } }
17.2.4、UserDao
package com.huiruan.dao; import com.huiruan.entity.User; import java.util.List; public interface UserDao { public int insert(User user); public int update(User user); public int delete(int id); public User seleteOne(int id); public List<User> seleteAll(); }
17.2.5、UserDaoImpl
package com.huiruan.dao.impl; import com.huiruan.dao.UserDao; import com.huiruan.entity.User; import com.huiruan.utils.DbUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import java.sql.SQLException; import java.util.List; public class UserDaoImpl implements UserDao { private QueryRunner queryRunner = new QueryRunner(DbUtils.getDruidDataSource()); @Override public int insert(User user) { try { String sql = "INSERT INTO `user` (`username`,`password`,`address`,`phone`) VALUE (?,?,?,?)"; Object[] params = {user.getUsername(),user.getPassword(),user.getAddress(),user.getPhone()}; return queryRunner.update(sql,params); } catch (SQLException e) { e.printStackTrace(); } return 0; } @Override public int update(User user) { try { String sql = "UPDATE `user` SET `username` = ?, `password`= ?, `address`= ?, `phone`= ? WHERE `userId` = ?"; Object[] params = {user.getUsername(),user.getPassword(),user.getAddress(),user.getPhone(),user.getUserId()}; return queryRunner.update(sql,params); } catch (SQLException e) { e.printStackTrace(); } return 0; } @Override public int delete(int id) { try { String sql = "DELETE FROM `user` WHERE `userId` = ?"; return queryRunner.update(sql,id); } catch (SQLException e) { e.printStackTrace(); } return 0; } @Override public User seleteOne(int id) { try { String sql = "SELECT * FROM `user` WHERE `userId` = ?"; return queryRunner.query(sql,new BeanHandler<User>(User.class),id); } catch (SQLException e) { e.printStackTrace(); } return null; } @Override public List<User> seleteAll() { try { String sql = "SELECT * FROM `user`"; return queryRunner.query(sql,new BeanListHandler<User>(User.class)); } catch (SQLException e) { e.printStackTrace(); } return null; } }

浙公网安备 33010602011771号