一、数据库连接回顾
1.1 之前如何操作数据库?
(1)使用DOS命令窗口,输入“mysql -hlocalhost -u数据库用户名 -p数据库密码”命令连接数据库,编写SQL语句(SQL语句以分号;或者\g结尾),回车运行,查看操作结果(受影响行数或结果集)
(2)使用MySQL数据库自带的命令窗口,输入数据库密码连接数据库,编写SQL语句(SQL语句以分号;或者\g结尾),回车运行,查看操作结果(受影响行数或结果集)
(3)使用数据库连接软件(SQLyog)连接数据库,通过图形化界面或者在查询编辑器中编写SQL语句,运行SQL语句查看操作结果(受影响行数或结果集)
1.2 实际开发中如何操作数据库?
在实际开发中,当用户的数据发生变化时,不会也不可能通过客户端连接数据库去操作SQL语句,因为在实际开发中,数据的操作量很大,如果使用客户端操作数据库,无法保证SQL语句的正确性和执行效率。
二、JDBC(Java Database Connectivity)
2.1 JDBC的概念
(1)JDBC(Java DataBase Connectivity)Java连接数据库的规范(标准),可以使用Java语言连接数据库,从而对数据进行增删改查(CURD)操作。
2.2 JDBC核心思想
Java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver数据库驱动)。
2.2.1 MySQL数据库驱动
mysql-connector-java-5.1.x 适用于5.x版本
mysql-connector-java-8.1.x 适用于8.x版本
2.2.2 JDBC API
JDBC是由多个接口和类进行功能实现的。
类型 | 权限定名 | 功能 |
---|---|---|
class | java.sql.DriverManager | 管理多个数据库驱动类,提供了获取数据库连接的方法 |
interface | java.sql.Connection | 代表一个数据库连接(当connection不为null时,表示已连接数据库) |
interface | java.sql.Statement | 发送SQL语句到数据库工具 |
interface | java.sql.PreparedStatement | 发送SQL语句到数据库工具 |
interface | java.sql.ResultSet | 保存SQL查询语句的结果数据(结果集) |
class | java.sql.SQLException | 处理数据库应用程序时所发生的异常 |
2.3 JDBC环境搭建
(1)在项目下创建lib文件夹,用于存放jar文件。
(2)将mysql驱动mysql-connector-java-5.1.x复制到项目的lib文件夹中。
(3)将选中lib文件中的jar文件配置到项目中。
2.4 准备一张表
创建数据库jdbcdatabase,专门用来存储学习jdbc要用的表
2.4.1 创建student表
CREATE TABLE IF NOT EXISTS `student`(
`tid` INT(10) AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(20) NOT NULL COMMENT '姓名',
`age` INT(2) NOT NULL COMMENT '年龄',
`gender` VARCHAR(5) NOT NULL COMMENT '性别',
`phone` VARCHAR(11) UNIQUE NOT NULL COMMENT '手机号码',
`identitycard` VARCHAR(18) UNIQUE NOT NULL COMMENT '身份证号码',
`address` VARCHAR(20) NOT NULL COMMENT '住址',
PRIMARY KEY (`tid`)
);
2.4.2 向表中插入数据
INSERT INTO `student`(`tid`,`name`,`age`,`gender`,`phone`,`identitycard`,`address`) VALUES (1001,'张三',20,'男','13112345678','340825200212241936','安徽合肥蜀山区');
INSERT INTO `student`(`tid`,`name`,`age`,`gender`,`phone`,`identitycard`,`address`) VALUES (1002,'李红',18,'女','13111223344','340825200408151936','安徽合肥庐阳区');
三、JDBC的开发步骤(非常重要)
3.1 注册驱动
使用Class.forName(“包含完整路径的驱动类”);//手动加载字节码文件到JVM中。
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
3.2 获取连接对象
通过DriverManager.getConnection(url,user,password)获取数据库连接对象
url:mysql数据库的路径
user:mysql数据库用户名
password:mysql数据库密码
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url, user, password);
3.3 获取发送SQL语句的对象
通过Connection对象获取Statement对象,用于发送SQL语句,实现对数据库进行访问。
//3、获取发送SQL语句的对象
Statement statement = connection.createStatement();
3.4 编写SQL语句
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误,这里sid是自增长,所以不需要写
String sql = "INSERT INTO `student`(`name`,`age`,`gender`,`phone`,`identitycard`,`address`)
VALUES ('王五',21,'男','13825869876','340825200109151928','安徽合肥包河区');";
3.5 执行SQL语句
// 5、执行SQL语句
//DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
//DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
3.6 处理结果
处理第5步返回的数据。对返回的受影响行数结果进行逻辑判断
// 6、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
3.7 释放资源
释放(关闭)所使用到的所有资源对象,遵循”先开的后关,后开的先关“原则。
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//查询操作中多一个关闭resultSet
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
3.8 综合案例
3.8.1 插入数据
综合上述7个步骤,实现向student表中插入一条数据。
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里student表中插入一条数据
*
*/
public class Jdbc01InsertStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误,这里sid是自增长,所以不需要写
String sql = "INSERT INTO `student`(`name`,`age`,`gender`,`phone`,`identitycard`,`address`) VALUES ('王五',21,'男','13825869876','340825200109151928','安徽合肥包河区');";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
3.8.2 删除数据
综合上述7个步骤,实现根据学号sid删除数据库表中一条数据。
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc02DeleteStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "DELETE FROM `student` WHERE `tid` = 1003;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
3.8.3 修改数据
综合上述7个步骤,实现根据学号sid修改数据库表中一条数据。
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc03UpdateStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `student` SET `name`='李红',`age`=19,`gender`='女',`phone`='13111223344',`identitycard`='340825200308151936',`address`='安徽合肥高新区' WHERE `sid`=1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
四、ResultSet(结果集)
JDBC中执行DQL查询语句后,使用ResultSet存放查询到的结果集数据。
4.1 接收结果集
ResultSet resultSet = statement.executeQuery(String sql);
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student` WHERE `sid`= 1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
ResultSet resultSet = statement.executeQuery(sql);
4.2 遍历ResultSet结果集中的数据
ResultSet以表(table)结构进行临时结果的存储,需要通过JDBC API将其中的数据依次获取。
数据行指针:初始位置在第一行数据前,每调用一次boolean next()方法ResultSet的指针向下移动一行,结果为true,表示当前行有数据。
- resultSet.getXxx(int columnIndex):根据字段的索引顺序获取表中字段的数据,索引从1开始,Xxx表示字段类型。
- resultSet.getXxx(String columnLabel):根据字段的名称获取表中字段的数据。
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
//查询一条数据,根据记录中字段的索引获取字段数据
if (resultSet.next()) {
//根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
System.out.println(sid + "-" + name + "-" + age + "-" + gender+ "-" + phone + "-" + identitycard + "-" + address);
}
//查询一条数据,根据记录中字段的名称获取字段数据
if (resultSet.next()) {
//根据记录中字段的名称获取字段数据
int sid = resultSet.getInt("sid");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
String phone = resultSet.getString("phone");
String identitycard = resultSet.getString("identitycard");
String address = resultSet.getString("address");
System.out.println(sid + "-" + name + "-" + age + "-" + gender+ "-" + phone + "-" + identitycard + "-" + address);
}
//查询所有数据,根据记录中字段的索引获取字段数据
while (resultSet.next()) {
//根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
System.out.println(sid + "-" + name + "-" + age + "-" + gender+ "-" + phone + "-" + identitycard + "-" + address);
}
//查询所有数据,根据记录中字段的名称获取字段数据
while (resultSet.next()) {
//根据记录中字段的名称获取字段数据
int sid = resultSet.getInt("sid");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
String phone = resultSet.getString("phone");
String identitycard = resultSet.getString("identitycard");
String address = resultSet.getString("address");
System.out.println(sid + "-" + name + "-" + age + "-" + gender+ "-" + phone + "-" + identitycard + "-" + address);
}
4.2.1 常用遍历方法
-
int getInt(int columnIndex) throws SQLException //获得当前行第N列的int值
-
int getInt(String columnLabel) throws SQLException //获得当前行名为cloumnLabel列的int值
-
int getDouble(int columnIndex) throws SQLException //获得当前行第N列的double值
-
int getDouble(String columnLabel) throws SQLException //获得当前行名为cloumnLabel列的double值
-
int getString(int columnIndex) throws SQLException //获得当前行第N列的String值
-
int getString(String columnLabel) throws SQLException //获得当前行名为cloumnLabel列的String值
4.3案例代码
4.3.1 查询一条数据
根据学号sid查询student表中的一条学生记录。
4.3.1.1 根据字段的索引获取数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现根据学号sid查询数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc04SelectOneStudent01 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student` WHERE `sid`= 1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
System.out.println(sid + "-" + name + "-" + age + "-" + gender
+ "-" + phone + "-" + identitycard + "-" + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
4.3.1.2 根据字段的名称获取数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现根据学号sid查询数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc04SelectOneStudent02 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student` WHERE `sid`= 1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的名称获取字段数据
int sid = resultSet.getInt("sid");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
String phone = resultSet.getString("phone");
String identitycard = resultSet.getString("identitycard");
String address = resultSet.getString("address");
System.out.println(sid + "-" + name + "-" + age + "-" + gender
+ "-" + phone + "-" + identitycard + "-" + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
4.3.2 查询所有数据
查询student表中所有的学生记录。
4.3.2.1 根据字段的索引获取数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现查询数据库jdbcdatabase里student表中的所有数据
*
*/
public class Jdbc05SelectAllStudent01 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student`;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
System.out.println(sid + "-" + name + "-" + age + "-" + gender
+ "-" + phone + "-" + identitycard + "-" + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
4.3.2.2 根据字段的名称获取数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现查询数据库jdbcdatabase里student表中的所有数据
*
*/
public class Jdbc05SelectAllStudent02 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student`;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的名称获取字段数据
int sid = resultSet.getInt("sid");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
String phone = resultSet.getString("phone");
String identitycard = resultSet.getString("identitycard");
String address = resultSet.getString("address");
System.out.println(sid + "-" + name + "-" + age + "-" + gender
+ "-" + phone + "-" + identitycard + "-" + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
五、ORM
(1)ORM(Object Relational Mapping),对象关系映射。
(2)从数据库查询到的结果集(ResultSet)在进行遍历时,逐行遍历,然后一个字段一个字段的读取数据,取出的都是零散的数据,然后将零散数据一个一个输出,这样比较麻烦,不利于操作。在实际应用开发中,我们需要将零散的数据进行封装整理。
(3)在Java中,将一个封装好的对象插入到数据库的student表中,也可以将查询出来的数据封装成一个对象。
5.1 实体类(entity):零散数据的载体
- 一行数据中,多个零散的数据进行整理,一行数据(在数据库中称之为一条记录或者一个实体)对应Java中的一个对象。
- 通过entity的规则对表中的数据进行对象的封装。
- 表名=类名;字段名=属性名;提供各个属性的getXxx()/setXxx()方法。
- 提供无参构造方法、有参构造方法
- 重写toString()方法
5.2 ORM应用步骤
5.2.1 创建entity实体类Student
package com.cxyzxc.www.examples02;
/**
* entity实体类Student
*
*/
public class Student {
/** 学号 */
private int sid;
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 性别 */
private String gender;
/** 手机号码 */
private String phone;
/** 身份证号码 */
private String identitycard;
/** 住址 */
private String address;
// 无参构造方法
public Student() {
super();
}
// 有参构造方法
public Student(String name, int age, String gender, String phone,
String identitycard, String address) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.phone = phone;
this.identitycard = identitycard;
this.address = address;
}
// 有参构造方法
public Student(int sid, String name, int age, String gender, String phone,
String identitycard, String address) {
super();
this.sid = sid;
this.name = name;
this.age = age;
this.gender = gender;
this.phone = phone;
this.identitycard = identitycard;
this.address = address;
}
// getXxx()/setXxx()方法
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getIdentitycard() {
return identitycard;
}
public void setIdentitycard(String identitycard) {
this.identitycard = identitycard;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// 重写toString()方法
@Override
public String toString() {
return "Student [sid=" + sid + ", name=" + name + ", age=" + age
+ ", gender=" + gender + ", phone=" + phone + ", identitycard="
+ identitycard + ", address=" + address + "]";
}
}
5.2.2 插入一条数据封装
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里student表中插入一条数据
*
*/
public class Jdbc01ORMInsertStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建Student类对象
Student student = new Student("李二牛", 28, "男", "13844556633", "340825199409192345", "安徽合肥经开区");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误,这里sid是自增长,所以不需要写
String sql = "INSERT INTO `student`(`name`,`age`,`gender`,`phone`,`identitycard`,`address`) VALUES ('"+student.getName()+"',"+student.getAge()+",'"+student.getGender()+"','"+student.getPhone()+"','"+student.getIdentitycard()+"','"+student.getAddress()+"');";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
5.2.3 删除一条数据封装
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc02ORMDeleteStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建Student类对象
Student student = new Student(1003,"李二狗", 28, "男", "13844556644", "340825199409192345", "安徽合肥高新区");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "DELETE FROM `student` WHERE `sid` = "+student.getSid()+";";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
5.2.4 修改一条数据封装
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc03ORMUpdateStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建Student类对象
Student student = new Student(1003,"李二狗", 28, "男", "13844556644", "340825199409192345", "安徽合肥高新区");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `student` SET `name`='"+student.getName()+"',`age`="+student.getAge()+",`gender`='"+student.getGender()+"',`phone`='"+student.getPhone()+"',`identitycard`='"+student.getIdentitycard()+"',`address`='"+student.getAddress()+"' WHERE `sid`="+student.getSid()+";";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
5.2.5 查询一条结果封装
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现根据学号sid查询数据库jdbcdatabase里student表中的一条数据
*
*/
public class Jdbc04ORMSelectOneStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
Student student = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student` WHERE `sid`= 1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
// System.out.println(sid + "-" + name + "-" + age + "-" +gender + "-" + phone + "-" + identitycard + "-" + address);
// 创建实体类对象
student = new Student();
// 给实体类对象属性赋值,也可以通过有参构造方法创建实体类对象并给对象属性赋值
student.setSid(sid);
student.setName(name);
student.setAge(age);
student.setGender(gender);
student.setPhone(phone);
student.setIdentitycard(identitycard);
student.setAddress(address);
//输出对象
System.out.println(student);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
5.2.6 查询所有结果封装
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC连接数据 实现查询数据库jdbcdatabase里student表中的所有数据
*
*/
public class Jdbc05ORMSelectAllStudent {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
Student student = null;
List<Student> studentList = new ArrayList<Student>();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `student`;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int sid = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
String phone = resultSet.getString(5);
String identitycard = resultSet.getString(6);
String address = resultSet.getString(7);
// System.out.println(sid + "-" + name + "-" + age + "-" + gender + "-" + phone + "-" + identitycard + "-" + address);
// 通过有参构造方法创建实体类对象
student = new Student(sid, name, age, gender, phone, identitycard, address);
// 输出对象
studentList.add(student);
}
// 遍历输出studentList集合中的数据
for (Student student2 : studentList) {
System.out.println(student2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
六、JDBC常见异常
- java.lang.ClassNotFoundException:找不到类(类名书写错误、没有导入jar包)
- java.sql.SQLException:与SQL语句相关的异常(约束错误、表名列名字段名书写错误),建议:在客户端工具中测试SQL语句正确后再复制到代码中
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:Unknown column原因:列值String类型没有加单引号
- Duplicate entry ‘1’ for key 'PRIMARY’原因,主键值已经存在或混乱,更改主键值或清空表
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:Unknown column ‘password’ in原因:可能输入的值类型不对,确定是否插入的元素是对应的值的类型正确
七、综合案例(账号密码登录)
7.1 准备一张表
7.1.1创建user表
表的字段如下:
id,用户编号,主键、自动增长。
username,用户名,字符串类型、唯一、非空。
password,密码,字符串类型、非空。
phone,手机号码,字符串类型
CREATE TABLE IF NOT EXISTS `user`(
`uid` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(10) UNIQUE NOT NULL,
`password` VARCHAR(10) NOT NULL,
`phone` VARCHAR(11)
);
7.1.2 向表中插入数据
向user表中插入两条数据:
INSERT INTO `user`(`uid`,`username`,`password`,`phone`) VALUES(1001,'zhangsan','123456','13112345678');
INSERT INTO `user`(`uid`,`username`,`password`,`phone`) VALUES(1002,'lisi','123456','13844445555');
7.2 JDBC实现增删改查
使用JDBC+ORM技术点实现对user表增删改查操作,巩固知识点。
7.2.1 创建entity实体类User
package com.cxyzxc.www.examples03;
/**
* entity类User类
*
*/
public class User {
/** 用户编号 */
private int uid;
/** 用户名 */
private String name;
/** 密码 */
private String password;
/** 手机号码 */
private String phone;
// 无参构造方法
public User() {
super();
}
// 有参构造方法
public User(String name, String password, String phone) {
super();
this.name = name;
this.password = password;
this.phone = phone;
}
// 有参构造方法
public User(int uid, String name, String password, String phone) {
super();
this.uid = uid;
this.name = name;
this.password = password;
this.phone = phone;
}
// getXxx()/setXxx()方法
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
// 重写toString()方法
@Override
public String toString() {
return "User [uid=" + uid + ", name=" + name + ", password=" + password
+ ", phone=" + phone + "]";
}
}
7.2.2 插入数据
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里user表中插入一条数据
*
*/
public class Jdbc01ORMInsertUser {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建User对象
User user2 = new User("王五", "123456", "13966669999");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误,这里sid是自增长,所以不需要写
String sql = "INSERT INTO `user`(`username`,`password`,`phone`) VALUES('"+user2.getName()+"','"+user2.getPassword()+"','"+user2.getPhone()+"');";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
7.2.3 删除数据
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc02ORMDeleteUser {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建对象
User user2 = new User(1003, "王五", "123456", "13966669999");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "DELETE FROM `user` WHERE `uid` = "+user2.getUid()+";";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
7.2.4 修改数据
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc03ORMUpdateUser {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
//创建User对象
User user2 = new User(1002, "李四", "112233", "13999998888");
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `user` SET `username`='"+user2.getName()+"',`password`='"+user2.getPassword()+"',`phone`='"+user2.getPhone()+"' WHERE `uid`="+user2.getUid()+";";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = statement.executeUpdate(sql);
// 6、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
7.2.5 查询数据
7.2.5.1 查询1条数据
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc04ORMSelectOneUser {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
User user = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `user` WHERE `uid`= 1002;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int uid = resultSet.getInt(1);
String username = resultSet.getString(2);
String password = resultSet.getString(3);
String phone = resultSet.getString(4);
//使用有参构造方法创建user对象
user = new User(uid, username, password, phone);
//输出对象
System.out.println(user);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
7.2.5.2 查询所有数据
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc05ORMSelectAllUser {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
User user = null;
List<User> userList = new ArrayList<User>();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `user`;";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int uid = resultSet.getInt(1);
String username = resultSet.getString(2);
String password = resultSet.getString(3);
String phone = resultSet.getString(4);
//使用有参构造方法创建user对象
user = new User(uid, username, password, phone);
//将创建的对象添加到集合中
userList.add(user);
}
//遍历集合,输出所有user对象
for (User user2 : userList) {
System.out.println(user2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
7.3 实现登录
需求:
- 通过Scanner对象在控制台输入用户名和密码。
- 将用户输入的用户名和密码作为条件,编写查询SQL语句,在第七节知识点中的user表中查询用户。
- 如果该用户存在,提示登录成功,反之提示登录失败。
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/**
* 登录类:Login类
*
*/
public class Login {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
//创建Scanner对象,获取用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、获取发送SQL语句对象
statement = connection.createStatement();
// 4、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "SELECT * FROM `user` WHERE `username`='"+username+"' AND `password` = '"+password+"';";
// 5、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = statement.executeQuery(sql);
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if(resultSet.next()){
System.out.println("用户名和密码正确,登录成功");
}else{
System.out.println("用户名或密码不正确,登录失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
sc.close();
}
}
}
八、SQL注入
8.1 SQL注入的效果的演示
8.1.1 SQL注入代码
参照上面的登录代码
8.1.2 SQL注入效果
输入错误的用户名和密码,提示登录失败:
输入错误的用户名和密码,提示登录成功:产生了SQL注入
![在这里插入图片描述](https://img-blog.csdnimg.cn/9f4a36654b5a45e28a001d2798729500.png#pic_center
8.2 什么是SQL注入
在用户输入的数据中有SQL关键字或语法,并且关键字或语法参与了SQL语句的编译。导致SQL语句编译后的条件为true,一直得到正确的结果。这种现象就是SQL注入。
上面案例代码中,当你的用户名为 qwert’ or 1=1;# 密码为123,拼接到SQL语句中,变成如下效果:
SELECT * FROM USER WHERE `username`='qwert' OR 1=1;#' AND `password` = '123';
此SQL语句or 后面1=1永远正确,#后面的成了注释,所以这条语句会将表中所有的数据查询出来,然后再做数据判断的时候,就会得到正确结果,从而说用户名和密码正确,登录成功
8.3 如何避免SQL注入
由于SQL注入产生的原因是在用户输入数据对SQL整合,整合后再发送到数据库进行编译产生的。所以为了避免SQL注入,就需要SQL语句在用户输入数据前就进行编译,成为完整的SQL语句,编译完成后再进行数据填充。这个操作需要使用PrepareStatement实现。
九、PrepareStatement解决SQL注入(重要)
PreparedStatement接口继承了Statement接口,执行SQL语句的方法与Statement执行SQL语句的方法相同。
9.1 PreparedStatement的应用
PreparedStatement的作用:
- 预编译SQL语句,效率高
- 安全,避免SQL注入
- 可以动态的填充数据,执行多个同结构的SQL语句
9.1.1 参数标记
//预编译SQL语句,SQL中的所有参数由?符号占位,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。
String sql = "select * from user where `username` = ? and `password`=?;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
9.1.2 动态参数绑定
preparedStatement.sexXxx(下标,值):参数下标从1开始,为指定参数下标绑定值。Xxx表示数据类型。
//绑定参数,有多少个?绑定多少个参数值
preparedStatement.setString(1, username);
preparedStatement.setString(2, pwd);
9.2 综合案例
9.2.1 PreparedStatement插入数据
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里user表中插入一条数据
*
*/
public class Jdbc01PreparedStatementInsertUser {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "INSERT INTO `user`(`username`,`password`,`phone`) VALUES(?,?,?);";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建对象
User user2 = new User("如花", "123456", "13311112222");
//5、绑定参数,给?赋值
preparedStatement.setString(1, user2.getName());
preparedStatement.setString(2, user2.getPassword());
preparedStatement.setString(3, user2.getPhone());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
9.2.2 PreparedStatement删除数据
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc02PreparedStatementDeleteUser {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "DELETE FROM `user` WHERE `uid` = ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//5、绑定参数,给?赋值
preparedStatement.setInt(1, 1003);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
9.2.3 PreparedStatement修改数据
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc03PreparedStatementUpdateUser {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `user` SET `username`=?,`password`=?,`phone`=? WHERE `uid`=?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建User对象
User user2 = new User(1002, "李四", "112233", "13955661133");
//5、绑定参数,给?赋值
preparedStatement.setString(1,user2.getName());
preparedStatement.setString(2,user2.getPassword());
preparedStatement.setString(3,user2.getPhone());
preparedStatement.setInt(4, user2.getUid());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
9.2.4 PreparedStatement查询数据
9.2.4.1 查询一条数据
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc04PreparedStatementSelectOneStudent {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
User user = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `user` WHERE `uid`= ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值
preparedStatement.setInt(1, 1002);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int uid = resultSet.getInt(1);
String username = resultSet.getString(2);
String password = resultSet.getString(3);
String phone = resultSet.getString(4);
//使用有参构造方法创建user对象
user = new User(uid, username, password, phone);
//输出对象
System.out.println(user);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
9.2.4.2 查询所有数据
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里user表中的一条数据
*
*/
public class Jdbc05PreparedStatementSelectAllStudent {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
User user = null;
List<User> userList = new ArrayList<User>();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `user`;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值,这里不需要绑定参数
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 7、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int uid = resultSet.getInt(1);
String username = resultSet.getString(2);
String password = resultSet.getString(3);
String phone = resultSet.getString(4);
//使用有参构造方法创建user对象
user = new User(uid, username, password, phone);
//将创建的对象添加到集合中
userList.add(user);
}
//遍历集合,输出所有user对象
for (User user2 : userList) {
System.out.println(user2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
9.2.5 PreparedStatement实现登录
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
/**
* PreparedStatement实现登录,解决SQL注入问题
*
*/
public class PreparedStatementLogin {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
//创建Scanner对象,获取用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `user` WHERE `username`=? AND `password` = ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//5、绑定参数,给?赋值
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 7、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if(resultSet.next()){
System.out.println("用户名和密码正确,登录成功");
}else{
System.out.println("用户名或密码不正确,登录失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
sc.close();
}
}
}
十、Date工具类
学完使用JDBC连接数据库并使用PrepareStatement类对表中数据进行增删改查后,我们做一个练习,对下列people表进行增删改查操作。
10.1 创建people表
10.1.1 创建表
创建一张用户表peopler,表的字段如下:
pid,编号,主键、自动增长
name,姓名,varchar(20)、非空
age,年龄,int(3),非空
gender,性别,varchar(3),非空
birthday,出生日期,Date类型,非空
identitycard,身份证号码,varchar(18) ,唯一,非空
phone,手机号码,字符串类型,唯一,非空
address,住址,varchar(20),非空
CREATE TABLE IF NOT EXISTS `people`(
`pid` INT PRIMARY KEY AUTO_INCREMENT COMMENT '编号',
`name` VARCHAR(20) NOT NULL COMMENT '姓名',
`age` INT(3) NOT NULL COMMENT '年龄',
`gender` VARCHAR(3) NOT NULL COMMENT '性别',
`birthday` DATE NOT NULL COMMENT '出生日期',
`identitycrd` VARCHAR(18) NOT NULL UNIQUE COMMENT '身份证号码',
`phone` VARCHAR(11) NOT NULL UNIQUE COMMENT '手机号码',
`address` VARCHAR(20) NOT NULL COMMENT '住址'
);
10.1.2 向表中添加数据
向people表中插入两条数据:
INSERT INTO `people`(`pid`,`name`,`age`,`gender`,`birthday`,`identitycrd`,`phone`,`address`)
VALUES
(1001,'张三',30,'男','1992-04-05','340825199204051920','13888885555','安徽合肥庐阳区');
INSERT INTO `people`(`pid`,`name`,`age`,`gender`,`birthday`,`identitycrd`,`phone`,`address`)
VALUES
(1002,'李红',28,'女','1994-04-15','340825199204151922','13888886666','安徽合肥瑶海区');
10.2 问题描述
在上述操作过程中发现如下问题:
-
数据库中存储的日期时间类型为java.sql.Date类型,Java应用层存储的日期时间类型为java.util.Date类型。
-
从数据库获取的日期时间类型数据可以直接赋值给Java应用层的日期时间类型变量,因为java.sql.Date类是java.util.Date类的子类,向上转型(父类引用指向子类对象)是可以直接赋值的。
-
Java应用层的日期时间类型数据不能直接存储在数据库中,需要进行相应的转换。
-
preparedStatement.setDate(int parameterIndex, Date x)中Date为java.sql.Date类型。
10.3 与日期时间相关的类
10.3.1 java.util.Date
(1)Java语言常规应用层面的日期时间类型,可以通过字符串创建对应的日期时间对象,但是已经过时。常用构造方法如下(很多构造方法已经过时):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3LfZxvU-1690879270297)(img/09java.util.date类的构造方法.png)]
(2)不能直接通过JDBC将java.util.Date类型数据插入到数据库中。
10.3.2 java.sql.Date
(1)不可以通过字符串创建对应的时间对象,只能通过毫秒值创建对象(1970年1月1日0点0分0秒至今的毫秒值),常用构造方法如下:
(2)可以直接通过JDBC将java.util.Date类型数据插入到数据库中。
10.3.3 SimpleDateFormat
(1)SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。
(2)SimpleDateFormat使得可以选择任何用户定义的日期-时间格式的模式。
(3)SimpleDateFormat应用如下:
package com.cxyzxc.www.examples05;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* SimpleDateFormat类应用
*
*/
public class SimpleDateFormatTest {
public static void main(String[] args) {
// 指定日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
String strDate1 = "2022-10-22";
// 将字字符串解析成日期类型(java.util.Date)
java.util.Date date1 = sdf.parse(strDate1);
System.out.println("字符串解析成日期:" + date1);
Date date2 = new Date();
String strDate2 = sdf.format(date2);
System.out.println("日期解析成字符串:" + strDate2);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
10.3 封装DateUtils工具类
package com.cxyzxc.www.examples05;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 日期时间工具类DateUtils
*
*/
public class DateUtils {
private static final SimpleDateFormat SIMPLEDATEFORMAT = new SimpleDateFormat("yyyy-MM-dd");
// 字符串转换为java.util.Date类型日期时间
public static java.util.Date strDateToUtilDate(String strDate) {
try {
return SIMPLEDATEFORMAT.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
// java.util.Date类型日期时间转换为java.sql.Date类型日期时间
public static java.sql.Date utilDateToSqlDate(java.util.Date date) {
// long date.getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT以来此 Date对象表示的毫秒数
return new java.sql.Date(date.getTime());
}
// java.util.Date类转换为字符串类型
public static String utilDateToString(java.util.Date date) {
return SIMPLEDATEFORMAT.format(date);
}
}
10.4 综合案例
10.4.1 创建entity类People类
package com.cxyzxc.www.examples05;
import java.util.Date;
/**
* entity实体类People类
*
*/
public class People {
/** 编号 */
private int pid;
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 性别 */
private String gender;
/** 出生日期 */
private Date birthday;
/** 身份证号码 */
private String identitycard;
/** 手机号码 */
private String phone;
/** 住址 */
private String address;
// 无参构造方法
public People() {
super();
}
// 有参构造方法
public People(String name, int age, String gender, Date birthday,
String identitycard, String phone, String address) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.birthday = birthday;
this.identitycard = identitycard;
this.phone = phone;
this.address = address;
}
// 有参构造方法
public People(int pid, String name, int age, String gender, Date birthday,
String identitycard, String phone, String address) {
super();
this.pid = pid;
this.name = name;
this.age = age;
this.gender = gender;
this.birthday = birthday;
this.identitycard = identitycard;
this.phone = phone;
this.address = address;
}
// getXxx()/setXxx()方法
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getIdentitycard() {
return identitycard;
}
public void setIdentitycard(String identitycard) {
this.identitycard = identitycard;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// 重写toString()方法
@Override
public String toString() {
return "People [pid=" + pid + ", name=" + name + ", age=" + age
+ ", gender=" + gender + ", birthday=" + birthday
+ ", identitycard=" + identitycard + ", phone=" + phone
+ ", address=" + address + "]";
}
}
10.4.2 插入数据
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里people表中插入一条数据
*
*/
public class Jdbc01PreparedStatementInsertPeople {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "INSERT INTO `people`(`name`,`age`,`gender`,`birthday`,`identitycard`,`phone`,`address`) VALUES(?,?,?,?,?,?,?);";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建People对象
People people = new People("王五", 30, "男", DateUtils.strDateToUtilDate("1992-04-05"), "340825199204051926", "13845691236", "安徽合肥庐阳区");
//5、绑定参数,给?赋值
preparedStatement.setString(1, people.getName());
preparedStatement.setInt(2,people.getAge());
preparedStatement.setString(3,people.getGender());
//setDate(Date date)方法中需要的参数date类型是java.sql.Date类型,People对象中的Date类型是java.util.Date,需要进行转换
preparedStatement.setDate(4,DateUtils.utilDateToSqlDate(people.getBirthday()));
preparedStatement.setString(5,people.getIdentitycard());
preparedStatement.setString(6, people.getPhone());
preparedStatement.setString(7, people.getAddress());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
10.4.3 删除数据
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里people表中的一条数据
*
*/
public class Jdbc02PreparedStatementDeletePeople {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "DELETE FROM `people` WHERE `pid` = ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//5、绑定参数,给?赋值
preparedStatement.setInt(1, 1003);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
10.4.4 修改数据
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里people表中的一条数据
*
*/
public class Jdbc03PreparedStatementUpdatePeople {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String user = "root";
String password = "123456";
connection = DriverManager.getConnection(url, user, password);
// 3、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `people` SET `name`=?,`age`=?,`gender`=?,`birthday`=?,`identitycard`=?,`phone`=?,`address`=? WHERE `pid`=?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建对象
People people = new People(1002, "李花花", 28, "女", DateUtils.strDateToUtilDate("1994-04-15"), "340825199404151922", "13122337788", "安徽合肥政务区");
//5、绑定参数,给?赋值
preparedStatement.setString(1,people.getName());
preparedStatement.setInt(2, people.getAge());
preparedStatement.setString(3,people.getGender());
preparedStatement.setDate(4, DateUtils.utilDateToSqlDate(people.getBirthday()));
preparedStatement.setString(5,people.getIdentitycard());
preparedStatement.setString(6,people.getPhone());
preparedStatement.setString(7,people.getAddress());
preparedStatement.setInt(8, people.getPid());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
10.4.5 查询数据
10.4.5.1 查询一条数据
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里people表中的一条数据
*
*/
public class Jdbc04PreparedStatementSelectOnePeople {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
People people = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `people` WHERE `pid`= ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值
preparedStatement.setInt(1, 1002);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int pid = resultSet.getInt(1);
String peopleName = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
Date birthday = resultSet.getDate(5);
String identitycard=resultSet.getString(6);
String phone =resultSet.getString(7);
String address=resultSet.getString(8);
//使用有参构造方法创建People对象
people = new People(pid, peopleName, age, gender, birthday, identitycard, phone, address);
//输出对象
System.out.println(people);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
10.4.5.2 查询所有数据
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* JDBC连接数据 实现根据编号pid查询数据库jdbcdatabase里people表中的一条数据
*
*/
public class Jdbc05PreparedStatementSelectAllPeople {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
People people = null;
List<People> peopleList = new ArrayList<People>();
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 、获取数据库连接对象
String url = "jdbc:mysql://127.0.0.1:3306/jdbcdatabase";
String name = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url, name, pwd);
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `people`;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值,这里不需要绑定参数
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 7、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int pid = resultSet.getInt(1);
String peopleName = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
Date birthday = resultSet.getDate(5);
String identitycard=resultSet.getString(6);
String phone =resultSet.getString(7);
String address=resultSet.getString(8);
//使用有参构造方法创建People对象
people = new People(pid, peopleName, age, gender, birthday, identitycard, phone, address);
//将创建的对象添加到集合中
peopleList.add(people);
}
//遍历集合,输出所有People对象
for (People People2 : peopleList) {
System.out.println(People2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
十一、封装工具类
11.1 为什么要封装工具类
- 在实际JDBC中的使用中,存在着大量的重复代码:例如连接数据库、关闭数据库这些操作。
- 我们需要把传统的JDBC代码进行重构,抽取出通用的JDBC工具类。以后连接任何数据库、释放资源都可以使用这个工具类。
11.2 重用性方案
11.2.1 方案思想
(1)新建一个工具类DBUtils。
(2)在工具类DBUtils类中封装获取连接、释放资源两个方法。
- 提供public static Connection getConnection(){}方法。
- 提供public static void closeAll(Connection connection,Statement statement,ResultSet resultSet){}方法
11.2.2 方案代码
package com.cxyzxc.www.examples01;
import java.sql.*;
/**
* 重用性方案 注册驱动 获取连接 释放资源
*
*/
public class DBUtils {
// 类加载,执行一次!
static {
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/jdbcdatabase", "root",
"123456");
} 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();
}
}
}
11.3 跨平台方案
11.3.1 方案思想
(1)在重用性方案中数据库的相关信息写在Java代码中,如果要修改数据库的相关信息,需要修改Java代码,比较麻烦,所以需要将数据库相关信息抽取出来放到一个专门的文件中存储。
(2)在项目src文件夹下创建db.properties文件,在文件中编写数据库驱动、数据库url、用户名、密码相关数据。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2217
username=root
password=123456
(2)在工具类DBUtils类中读取db.properties配置文件数据。
定义private static final Properties PROPERTIES = new Properties();//读取配置文件的Map
定义static{
//通过复用本类自带流,读取配置文件中的数据
InputStream is = DBUtils.class.getResourceAsStream("配置文件路径");
// 通过prop对象将流中的配置信息分隔成键值对
PROPERTIES.load(is);
//通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
String driverName=PROPERTIES.getProperty("driver");
//注册驱动
Class.forName(driverName);
}
(3)在工具类DBUtils类中封装获取连接、释放资源两个方法。
- 提供public static Connection getConnection(){}方法。
- 提供public static void closeAll(Connection connection,Statement statement,ResultSet resultSet){}方法
11.3.2 方案代码
package com.cxyzxc.www.examples02;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 跨平台方案 注册驱动 获取连接 释放资源
*
*/
public class DBUtils {
// //读取配置文件的Map
private static final Properties PROPERTIES = new Properties();
static {
// 通过复用本类自带流,读取配置文件中的数据
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
try {
// 通过prop对象将流中的配置信息分隔成键值对,将配置文件内容加载到properties集合
PROPERTIES.load(is);
// 注册驱动,通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
Class.forName(PROPERTIES.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(
PROPERTIES.getProperty("url"),
PROPERTIES.getProperty("username"),
PROPERTIES.getProperty("password"));
} 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();
}
}
}
11.4 综合案例(重复性方案)
11.4.1 创建animal表
11.4.1.1 创建表
CREATE TABLE IF NOT EXISTS `animal`(
`aid` INT PRIMARY KEY AUTO_INCREMENT COMMENT '宠物编号',
`type` VARCHAR(10) NOT NULL COMMENT '类型',
`name` VARCHAR(10) NOT NULL COMMENT '名字',
`age` INT NOT NULL COMMENT '年龄',
`gender` VARCHAR(3) NOT NULL COMMENT '性别',
`birthday` DATE NOT NULL COMMENT '出生日期'
);
11.4.1.2 插入数据
INSERT INTO `animal`(`aid`,`type`,`name`,`age`,`gender`,`birthday`)
VALUES
(1001,'狗','旺财',3,'公','2019-12-18');
INSERT INTO `animal`(`aid`,`type`,`name`,`age`,`gender`,`birthday`)
VALUES
(1002,'猫','阿狸',2,'母','2020-03-27');
11.4.2 创建entity类Animal类
package com.cxyzxc.www.examples01;
import java.util.Date;
public class Animal {
/** 宠物编号 */
private int aid;
/** 类型 */
private String type;
/** 名字 */
private String name;
/** 年龄 */
private int age;
/** 性别 */
private String gender;
/** 出生日期 */
private Date birthday;
// 无参构造方法
public Animal() {
super();
}
// 有参构造方法
public Animal(String type, String name, int age, String gender,
Date birthday) {
super();
this.type = type;
this.name = name;
this.age = age;
this.gender = gender;
this.birthday = birthday;
}
// 有参构造方法
public Animal(int aid, String type, String name, int age, String gender,
Date birthday) {
super();
this.aid = aid;
this.type = type;
this.name = name;
this.age = age;
this.gender = gender;
this.birthday = birthday;
}
// getXxx()/setXxx()方法
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
// 重写toString()方法
@Override
public String toString() {
return "Animal [aid=" + aid + ", type=" + type + ", name=" + name
+ ", age=" + age + ", gender=" + gender + ", birthday="
+ birthday + "]";
}
}
11.4.3 插入数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里animal表中插入一条数据
*
*/
public class Jdbc01PreparedStatementInsertAnimal {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
// 2、获取连接对象
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "INSERT INTO `animal`(`type`,`name`,`age`,`gender`,`birthday`) VALUES(?,?,?,?,?);";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 创建People对象
Animal animal = new Animal("狗", "来福", 2, "公",DateUtils.strDateToUtilDate("2020-11-02"));
// 5、绑定参数,给?赋值
preparedStatement.setString(1, animal.getType());
preparedStatement.setString(2, animal.getName());
preparedStatement.setInt(3, animal.getAge());
preparedStatement.setString(4, animal.getGender());
// setDate(Date
// date)方法中需要的参数date类型是java.sql.Date类型,animal对象中的Date类型是java.util.Date,需要进行转换
preparedStatement.setDate(5,DateUtils.utilDateToSqlDate(animal.getBirthday()));
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.4.4 删除数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里people表中的一条数据
*
*/
public class Jdbc02PreparedStatementDeleteAnimal {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "DELETE FROM `animal` WHERE `aid` = ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//5、绑定参数,给?赋值
preparedStatement.setInt(1, 1003);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.4.5 修改数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里animal表中的一条数据
*
*/
public class Jdbc03PreparedStatementUpdateAnimal {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `animal` SET `type`=?,`name`=?,`age`=?,`gender`=?,`birthday`=? WHERE `aid`=?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建对象
Animal animal = new Animal(1002,"猫","Tom",2,"公",DateUtils.strDateToUtilDate("2020-06-11"));
//5、绑定参数,给?赋值
preparedStatement.setString(1,animal.getType());
preparedStatement.setString(2, animal.getName());
preparedStatement.setInt(3,animal.getAge());
preparedStatement.setString(4,animal.getGender());
preparedStatement.setDate(5, DateUtils.utilDateToSqlDate(animal.getBirthday()));
preparedStatement.setInt(6,animal.getAid());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.4.5 查询数据
11.4.5.1 查询一条数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里animal表中的一条数据
*
*/
public class Jdbc04PreparedStatementSelectOneAnimal {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Animal animal = null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `animal` WHERE `aid`= ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值
preparedStatement.setInt(1, 1001);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int aid = resultSet.getInt(1);
String type = resultSet.getString(2);
String name = resultSet.getString(3);
int age = resultSet.getInt(4);
String gender=resultSet.getString(5);
Date birthday = resultSet.getDate(6);
//使用有参构造方法创建Animal对象
animal = new Animal(aid, type, name, age, gender, birthday);
//输出对象
System.out.println(animal);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
}
}
11.4.5.2 查询所有数据
package com.cxyzxc.www.examples01;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* JDBC连接数据 实现根据编号pid查询数据库jdbcdatabase里animal表中的一条数据
*
*/
public class Jdbc05PreparedStatementSelectAllAnimal {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Animal animal = null;
List<Animal> animalList = new ArrayList<Animal>();
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `animal`;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值,这里不需要绑定参数
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 7、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int aid = resultSet.getInt(1);
String type = resultSet.getString(2);
String name = resultSet.getString(3);
int age = resultSet.getInt(4);
String gender=resultSet.getString(5);
Date birthday = resultSet.getDate(6);
//使用有参构造方法创建Animal对象
animal = new Animal(aid, type, name, age, gender, birthday);
//将创建的对象添加到集合中
animalList.add(animal);
}
//遍历集合,输出所有People对象
for (Animal animal2 : animalList) {
System.out.println(animal2);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
}
}
11.5 综合案例(跨平台方案)
11.5.1 创建car表
11.5.1.1 创建表
CREATE TABLE IF NOT EXISTS `car`(
`cid` INT PRIMARY KEY AUTO_INCREMENT COMMENT '编号',
`brand` VARCHAR(10) NOT NULL COMMENT '品牌',
`type` VARCHAR(10) NOT NULL COMMENT '型号',
`color` VARCHAR(10) NOT NULL COMMENT '颜色',
`birthday` DATE NOT NULL COMMENT '出厂日期',
`vin` VARCHAR(20) UNIQUE NOT NULL COMMENT '车架号',
`price` DOUBLE NOT NULL COMMENT '价格'
);
11.5.1.2 插入数据
INSERT INTO `car`(`cid`,`brand`,`type`,`color`,`birthday`,`vin`,`price`)
VALUES
(1001,'吉利','星越L','蓝色','2021-11-19','34091564784664WK45',156800);
INSERT INTO `car`(`cid`,`brand`,`type`,`color`,`birthday`,`vin`,`price`)
VALUES
(1002,'奔驰','E300','黑色','2021-11-19','35291579654688BC45',352800);
11.5.2 创建entity类Car类
package com.cxyzxc.www.examples02;
import java.util.Date;
public class Car {
/** 编号 */
private int cid;
/** 品牌 */
private String brand;
/** 型号 */
private String type;
/** 颜色 */
private String color;
/** 出厂日期 */
private Date birthday;
/** 车架号 */
private String vin;
/** 价格 */
private String price;
// 无参构造方法
public Car() {
super();
}
// 有参构造方法
public Car(String brand, String type, String color, Date birthday,
String vin, String price) {
super();
this.brand = brand;
this.type = type;
this.color = color;
this.birthday = birthday;
this.vin = vin;
this.price = price;
}
// 有参构造方法
public Car(int cid, String brand, String type, String color, Date birthday,
String vin, String price) {
super();
this.cid = cid;
this.brand = brand;
this.type = type;
this.color = color;
this.birthday = birthday;
this.vin = vin;
this.price = price;
}
// getXxx()/setXxx()方法
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getVin() {
return vin;
}
public void setVin(String vin) {
this.vin = vin;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
// 重写toString()方法
@Override
public String toString() {
return "Car [cid=" + cid + ", brand=" + brand + ", type=" + type
+ ", color=" + color + ", birthday=" + birthday + ", vin="
+ vin + ", price=" + price + "]";
}
}
11.5.3 插入数据
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现向数据库jdbcdatabase里car表中插入一条数据
*
*/
public class Jdbc01PreparedStatementInsertCar {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
// 2、获取连接对象
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "INSERT INTO `car`(`brand`,`type`,`color`,`birthday`,`vin`,`price`) VALUES(?,?,?,?,?,?);";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 创建People对象
Car car = new Car("奥迪", "A8", "黑色", DateUtils.strDateToUtilDate("2021-12-17"), "452915723546EYBC45", 1365200);
// 5、绑定参数,给?赋值
preparedStatement.setString(1, car.getBrand());
preparedStatement.setString(2, car.getType());
preparedStatement.setString(3, car.getColor());
// setDate(Date date)方法中需要的参数date类型是java.sql.Date类型,car对象中的Date类型是java.util.Date,需要进行转换
preparedStatement.setDate(4, DateUtils.utilDateToSqlDate(car.getBirthday()));
preparedStatement.setString(5, car.getVin());
preparedStatement.setDouble(6, car.getPrice());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据插入成功
if (result != 0) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.5.4 删除数据
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现删除数据库jdbcdatabase里car表中的一条数据
*
*/
public class Jdbc02PreparedStatementDeleteCar {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "DELETE FROM `car` WHERE `cid` = ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//5、绑定参数,给?赋值
preparedStatement.setInt(1, 1003);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据删除成功
if (result != 0) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.5.5 修改数据
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC连接数据 实现修改数据库jdbcdatabase里car表中的一条数据
*
*/
public class Jdbc03PreparedStatementUpdateCar {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement =null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句最好是先在SQLyog里面写一遍并运行一下,保证SQL语句没有语法错误
String sql = "UPDATE `car` SET `brand`=?,`type`=?,`color`=?,`birthday`=?,`vin`=?,`price`=? WHERE `cid`=?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
//创建对象
Car car = new Car(1002, "奔驰", "E330", "黑色", DateUtils.strDateToUtilDate("2022-01-11"), "45291579664688WD45", 415600);
//5、绑定参数,给?赋值
preparedStatement.setString(1,car.getBrand());
preparedStatement.setString(2, car.getType());
preparedStatement.setString(3,car.getColor());
preparedStatement.setDate(4, DateUtils.utilDateToSqlDate(car.getBirthday()));
preparedStatement.setString(5,car.getVin());
preparedStatement.setDouble(6,car.getPrice());
preparedStatement.setInt(7,car.getCid());
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
int result = preparedStatement.executeUpdate();
// 7、处理结果,如果返回的受影响行数不为0,说明数据修改成功
if (result != 0) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, null);
}
}
}
11.5.5 查询数据
11.5.5.1 查询一条数据
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* JDBC连接数据 实现根据学号uid查询数据库jdbcdatabase里car表中的一条数据
*
*/
public class Jdbc04PreparedStatementSelectOneCar {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Car car = null;
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `car` WHERE `cid`= ?;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值
preparedStatement.setInt(1, 1002);
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 6、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
if (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int cid = resultSet.getInt(1);
String brand = resultSet.getString(2);
String type = resultSet.getString(3);
String color = resultSet.getString(4);
Date birthday=resultSet.getDate(5);
String vin = resultSet.getString(6);
double price =resultSet.getDouble(7);
//使用有参构造方法创建Animal对象
car = new Car(cid, brand, type, color, birthday, vin, price);
//输出对象
System.out.println(car);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
}
}
11.5.5.2 查询所有数据
package com.cxyzxc.www.examples02;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* JDBC连接数据 实现根据编号pid查询数据库jdbcdatabase里car表中的一条数据
*
*/
public class Jdbc05PreparedStatementSelectAllCar {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Car car = null;
List<Car> carList = new ArrayList<Car>();
try {
connection = DBUtils.getConnection();
// 3、编写SQL语句,SQL语句中需要的数据先使用占位符?表示,然后在执行前给占位符赋值
String sql = "SELECT * FROM `car`;";
// 4、获取发送SQL语句对象
preparedStatement = connection.prepareStatement(sql);
// 5、绑定参数,给?赋值,这里不需要绑定参数
// 6、执行SQL语句
// DML语句:对于插入数据、修改数据、删除数据操作,都调用executeUpdate()方法,返回受影响的行数(int类型)
// DQL语句:对于查询数据,调用executeQuery()方法,返回一个结果集(ResultSet类型)
resultSet = preparedStatement.executeQuery();
// 7、处理结果,对返回的resultSet结果集进行处理,需要将结果集中的数据取出来
// 查询一条数据时,使用if判断resultSet.next()为true,说明resultSet结果集中有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据。
// 查询所有数据时,使用while循环判断resultSet.next()为true,说明resultSet结果集中还有一条数据,如果resultSet.next()为false,说明resultSet结果集中没有数据了。
while (resultSet.next()) {
// 根据记录中字段的索引获取字段数据,字段索引从1开始
int cid = resultSet.getInt(1);
String brand = resultSet.getString(2);
String type = resultSet.getString(3);
String color = resultSet.getString(4);
Date birthday=resultSet.getDate(5);
String vin = resultSet.getString(6);
double price =resultSet.getDouble(7);
//使用有参构造方法创建Animal对象
car = new Car(cid, brand, type, color, birthday, vin, price);
//将创建的对象添加到集合中
carList.add(car);
}
//遍历集合,输出所有People对象
for (Car car2 : carList) {
System.out.println(car2);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 8、释放资源,遵循“先开后关,后开先关”的原则
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
}
}
十二、DAO数据访问对象(Data Access Object)
(1)DAO(Data Access Object) ,数据访问对象,是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。
(2)之前代码中,业务逻辑代码和对数据库的访问操作代码全部写在一个类中,比较混乱,使用DAO实现业务逻辑与数据库访问相分离。
- 对同一张表的所有操作(增删改查,定义成方法)封装在XxxDaoImpl类中。Xxx表示实体类名
- 根据增删改查的不同功能实现具体的方法(insert、update、delete、select、selectAll)。
12.1 创建表teacher
1、创建一张教师表teacher,表的字段如下:
tid,教师编号,主键、自动增长。
name,教师姓名,字符串类型、非空。
age,年龄,int类型、非空。
bornDate,Date类型
email,邮箱,字符串类型,非空
address,住址,字符串类型,非空
CREATE TABLE IF NOT EXISTS `teacher`(
`tid` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(10) NOT NULL,
`age` INT NOT NULL,
`bornDate` DATE,
`email` VARCHAR(30) NOT NULL,
`address` VARCHAR(30) NOT NULL
);
2、向teacher表中插入两条数据:
INSERT INTO `teacher` VALUES(1001,'zhangsan',29,'1993-11-26','[email protected]','安徽合肥蜀山区长江西路132号');
INSERT INTO `teacher` VALUES(1002,'lisi',31,'1991-9-16','[email protected]','安徽合肥新站区环城西路12号');
12.2 封装实体类Teacher
创建entity实体类Teacher类,封装属性,添加无参构造方法和有参构造方法,添加getXxx()/setXxx()方法
package com.cxyzxc.www.examples03;
/**
* entity实体类Teacher类
*
*/
import java.util.Date;
public class Teacher {
/** 教师编号 */
private int tid;
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 出生日期 */
private Date bornDate;
/** 邮箱 */
private String email;
/** 住址 */
private String address;
// 无参构造方法
public Teacher() {
super();
}
// 有参构造方法
public Teacher(String name, int age, Date bornDate, String email,
String address) {
super();
this.name = name;
this.age = age;
this.bornDate = bornDate;
this.email = email;
this.address = address;
}
public Teacher(int tid, String name, int age, Date bornDate, String email,
String address) {
super();
this.tid = tid;
this.name = name;
this.age = age;
this.bornDate = bornDate;
this.email = email;
this.address = address;
}
// getXxx()/setXxx()方法
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int 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;
}
// 重写Object类中的toString()方法
@Override
public String toString() {
return "tid=" + tid + ", name=" + name + ", age=" + age + ", bornDate="
+ bornDate + ", email=" + email + ", address=" + address;
}
}
12.3 编写TeacherDaoImpl类
编写TeacherDaoImpl类,提供增删改查方法,使用JDBC完成开发功能。
package com.cxyzxc.www.examples03;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
*/
public class TeacherDaoImpl {
/*
* (1)该类中提供对teacher表进行增、删、改、查单个、查所有5个方法。
*
* (2)该类中的代码只做数据库访问操作,不做任何业务逻辑操作。
*
* (3)该类只对数据库一张表进行操作,从而实现复用
*/
// 新增:向teacher表中插入一条数据(一条数据对应一个Teacher对象),插入成功,返回一个受影响行数值(int类型)
public int insert(Teacher teacher) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "insert into `teacher`(name,age,bornDate,email,address) values(?,?,?,?,?);";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setString(1, teacher.getName());
preparedStatement.setInt(2, teacher.getAge());
// 将java.util.Date类型日期时间转换为java.sql.Date类型,然后插入到数据库中
preparedStatement.setDate(3,DateUtils.utilDateToSqlDate(teacher.getBornDate()));
preparedStatement.setString(4, teacher.getEmail());
preparedStatement.setString(5, teacher.getAddress());
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 删除:根据教师tid删除一条数据,删除成功,返回一个受影响行数值(int类型)
public int delete(int tid) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "delete from teacher where tid = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setInt(1, tid);
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 修改:修改teacher表中的数据,可能对任意的一个字段进行修改,所以方法中直接传递一个对象进行修改,修改成功,返回一个受影响行数值(int类型)
public int update(Teacher teacher) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "update teacher set name = ?,age = ?,bornDate = ?,email = ?,address = ? where tid = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setString(1, teacher.getName());
preparedStatement.setInt(2, teacher.getAge());
// 将java.util.Date类型日期时间转换为java.sql.Date类型,然后插入到数据库中
preparedStatement.setDate(3,DateUtils.utilDateToSqlDate(teacher.getBornDate()));
preparedStatement.setString(4, teacher.getEmail());
preparedStatement.setString(5, teacher.getAddress());
preparedStatement.setInt(6, teacher.getTid());
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 查询单个:根据教师tid查询一条数据,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成一个Teacher对象,将该对象返回
public Teacher select(int tid) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Teacher teacher = null;
String sql = "select * from teacher where tid = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setInt(1, tid);
resultSet = preparedStatement.executeQuery();
// 处理结果集,因为是查询单个数据,所以不需要循环遍历获取数据,集合中有数据就取出来
if (resultSet.next()) {
teacher = new Teacher();
int teacherid = resultSet.getInt("tid");
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");
// 将获取的赋值给teacher对象
teacher.setTid(teacherid);
teacher.setName(name);
teacher.setAge(age);
teacher.setBornDate(bornDate);
teacher.setEmail(email);
teacher.setAddress(address);
}
return teacher;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
return null;
}
// 查询所有:将teacher表中的所有数据全部查询出来,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成多个Teacher对象,将多个对象存储在集合中,返回这个集合
public List<Teacher> selectAll() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Teacher teacher = null;
List<Teacher> teacherList = new ArrayList<Teacher>();
String sql = "select * from teacher;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
// 查询出来多个结果,存在resultSet结果集中,遍历该结果集
while (resultSet.next()) {
int teacherid = resultSet.getInt("tid");
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");
teacher = new Teacher(teacherid, name, age, bornDate, email,address);
teacherList.add(teacher);
}
return teacherList;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
return null;
}
}
12.4 测试
12.4.1 测试增加数据
package com.cxyzxc.www.examples03;
public class TestTeacherDaoImpl01Insert {
public static void main(String[] args) {
// 创建TteacherDaoImpl类对象
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
// 创建字符串类型的日期
String strDate = "1992-03-22";
// 创建Teacher类对象
// DateUtils.strDateToUtilDate(strDate):将字符串类型的日期时间转换为java.util.Date类型
Teacher teacher = new Teacher("王五", 32,DateUtils.strDateToUtilDate(strDate), "[email protected]","安徽合肥蜀山区淠河路200号");
// 将teacher对象插入到数据库teacher表中
int result = teacherDaoImpl.insert(teacher);
if (result == 1) {
System.out.println("数据插入成功");
} else {
System.out.println("数据插入失败");
}
}
}
12.4.2 测试删除数据
package com.cxyzxc.www.examples03;
public class TestTeacherDaoImpl02Delete {
public static void main(String[] args) {
// 创建TteacherDaoImpl类对象
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
int result = teacherDaoImpl.delete(1003);
if (result == 1) {
System.out.println("数据删除成功");
} else {
System.out.println("数据删除失败");
}
}
}
12.4.3 测试修改数据
package com.cxyzxc.www.examples03;
public class TestTeacherDaoImpl03Update {
public static void main(String[] args) {
// 创建TteacherDaoImpl类对象
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
//创建字符串类型日期时间
String strDate = "2000-03-22";
// 创建Teacher类对象
//DateUtils.strDateToUtilDate(strDate):将字符串类型的日期时间转换为java.util.Date类型
Teacher teacher = new Teacher(1002,"李四", 22, DateUtils.strDateToUtilDate(strDate), "[email protected]","安徽合肥蜀山区淠河路19号");
// 将teacher对象插入到数据库teacher表中
int result = teacherDaoImpl.update(teacher);
if (result == 1) {
System.out.println("数据修改成功");
} else {
System.out.println("数据修改败");
}
}
}
12.4.4 测试查询单个
package com.cxyzxc.www.examples03;
public class TestTeacherDaoImpl04SelectOne {
public static void main(String[] args) {
// 创建TteacherDaoImpl类对象
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
Teacher teacher = teacherDaoImpl.select(1001);
if (teacher != null) {
System.out.println(teacher);
} else {
System.out.println("没有这个老师");
}
}
}
12.4.5 测试查询所有
package com.cxyzxc.www.examples03;
import java.util.List;
public class TestTeacherDaoImpl05SelectAll {
public static void main(String[] args) {
// 创建TteacherDaoImpl类对象
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
List<Teacher> teacherList = teacherDaoImpl.selectAll();
// 遍历teacherList集合
for (Teacher teacher : teacherList) {
System.out.println(teacher);
}
}
}
十三、Service业务逻辑层
13.1 什么是业务
(1)业务即用户完成的一个功能,可以有一个或者多个Dao的调用组成。(软件所提供的一个功能都叫业务)。
(2)你去银行取钱是一个业务,存钱是另一个业务,生活中你做的任何一件事都可以看成是一个业务。有的业务只需要一步就能完成,有的业务需要多个步骤才能完成。
13.2 service开发流程(注册账号业务)
13.2.1 业务需求和逻辑
(1)业务需求:
- 注册一个employee账户,存入employee表中
(2)业务逻辑:
- 首先在数据库中查询你要注册的账号是否存在(根据身份证号码查询,身份证号码具有唯一性)
- 如果查询不到你想要注册的账号,则将你注册的账号存入employee表中
- 如果查询到了你要注册的账号名称,则提示账号已存在,不能注册
13.2.2 业务实现步骤
1、创建表employee
CREATE TABLE IF NOT EXISTS `employee`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
`age` INT NOT NULL,
`gender` VARCHAR(3),
`bornDate` DATE NOT NULL,
`identityCard` VARCHAR(18) UNIQUE NOT NULL,
`phone` VARCHAR(11) NOT NULL,
`email` VARCHAR(20) NOT NULL,
`address` VARCHAR(30) NOT NULL
);
2、向employee表中插入数据
INSERT INTO `employee` VALUES(1001,'zhangsan',24,'男','1998-12-16','340825199812161316','13845687890','[email protected]','安徽合肥蜀山区');
INSERT INTO `employee` VALUES(1002,'lisi',25,'男','1997-12-26','340825199712261396','13845682233','[email protected]','安徽合肥瑶海区');
3、封装实体类Employee
package com.cxyzxc.www.examples04;
import java.util.Date;
/**
* entity实体类Employee
*
*/
public class Employee {
/** 员工编号 */
private int id;
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 性别 */
private String gender;
/** 出生日期 */
private Date bornDate;
/** 身份证号码 */
private String identityCard;
/** 手机号码 */
private String phone;
/** 邮箱 */
private String email;
/** 住址 */
private String address;
// 无参构造方法
public Employee() {
super();
}
// 有参构造方法
public Employee(String name, int age, String gender, Date bornDate,
String identityCard, String phone, String email, String address) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.bornDate = bornDate;
this.identityCard = identityCard;
this.phone = phone;
this.email = email;
this.address = address;
}
public Employee(int id, String name, int age, String gender, Date bornDate,
String identityCard, String phone, String email, String address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.bornDate = bornDate;
this.identityCard = identityCard;
this.phone = phone;
this.email = email;
this.address = address;
}
// getXxx()/setXxx()方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBornDate() {
return bornDate;
}
public void setBornDate(Date bornDate) {
this.bornDate = bornDate;
}
public String getIdentityCard() {
return identityCard;
}
public void setIdentityCard(String identityCard) {
this.identityCard = identityCard;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
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;
}
// 重写Object类中的toString()方法
@Override
public String toString() {
return "id=" + id + ", name=" + name + ", age=" + age + ", gender="
+ gender + ", bornDate=" + bornDate + ", identityCard="
+ identityCard + ", phone=" + phone + ", email=" + email
+ ", address=" + address;
}
}
4、编写EmployeeDaoImpl类(Dao层代码)
package com.cxyzxc.www.examples04;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EmployeeDaoImpl {
/*
* (1)该类中提供对teacher表进行增、删、改、查单个、查所有5个方法。
*
* (2)该类中的代码只做数据库访问操作,不做任何业务逻辑操作。
*
* (3)该类只对数据库一张表进行操作,从而实现复用
*/
// 新增:向employee表中插入一条数据(一条数据对应一个Employee对象),插入成功,返回一个受影响行数值(int类型)
public int insert(Employee employee) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "insert into `employee`(name,age,gender,bornDate,identityCard,phone,email,address) values(?,?,?,?,?,?,?,?);";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setString(1, employee.getName());
preparedStatement.setInt(2, employee.getAge());
preparedStatement.setString(3, employee.getGender());
// 将java.util.Date类型日期时间转换为java.sql.Date类型,然后插入到数据库中
preparedStatement.setDate(4,DateUtils.utilDateToSqlDate(employee.getBornDate()));
preparedStatement.setString(5, employee.getIdentityCard());
preparedStatement.setString(6, employee.getPhone());
preparedStatement.setString(7, employee.getEmail());
preparedStatement.setString(8, employee.getAddress());
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 删除:根据员工id删除一条数据,删除成功,返回一个受影响行数值(int类型)
public int delete(int id) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "delete from employee where id = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setInt(1, id);
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 修改:修改employee表中的数据,可能对任意的一个字段进行修改,所以方法中直接传递一个对象进行修改,修改成功,返回一个受影响行数值(int类型)
public int update(Employee employee) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "update employee set name = ?,age = ?,gender = ?,bornDate = ?,identityCard = ?,phone = ?,email = ?,address = ? where id = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
// 绑定参数,赋值
preparedStatement.setString(1, employee.getName());
preparedStatement.setInt(2, employee.getAge());
preparedStatement.setString(3, employee.getGender());
// 将java.util.Date类型日期时间转换为java.sql.Date类型,然后插入到数据库中
preparedStatement.setDate(4,DateUtils.utilDateToSqlDate(employee.getBornDate()));
preparedStatement.setString(5, employee.getIdentityCard());
preparedStatement.setString(6, employee.getPhone());
preparedStatement.setString(7, employee.getEmail());
preparedStatement.setString(8, employee.getAddress());
preparedStatement.setInt(9, employee.getId());
// 执行SQL语句,返回受影响的行数值
int result = preparedStatement.executeUpdate();
// 将结果返回给调用者
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 查询单个:根据员工id查询一条数据,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成一个Employee对象,将该对象返回
public Employee select(int id) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Employee employee = null;
String sql = "select * from employee where id = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setInt(1, id);
resultSet = preparedStatement.executeQuery();
// 处理结果集,因为是查询单个数据,所以不需要循环遍历获取数据,集合中有数据就取出来
if (resultSet.next()) {
employee = new Employee();
int employeeid = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
Date bornDate = resultSet.getDate("bornDate");
String identityCard = resultSet.getString("identityCard");
String phone = resultSet.getString("phone");
String email = resultSet.getString("email");
String address = resultSet.getString("address");
// 将获取的赋值给teacher对象
employee.setId(employeeid);
employee.setName(name);
employee.setAge(age);
employee.setGender(gender);
employee.setBornDate(bornDate);
employee.setIdentityCard(identityCard);
employee.setPhone(phone);
employee.setEmail(email);
employee.setAddress(address);
}
return employee;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return null;
}
// 查询单个:根据员工身份证号码查询一条数据,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成一个Employee对象,将该对象返回
public Employee select(String identityCard) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Employee employee = null;
String sql = "select * from employee where identityCard = ?;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数,赋值
preparedStatement.setString(1, identityCard);
resultSet = preparedStatement.executeQuery();
// 处理结果集,因为是查询单个数据,所以不需要循环遍历获取数据,集合中有数据就取出来
if (resultSet.next()) {
employee = new Employee();
int employeeid = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
Date bornDate = resultSet.getDate("bornDate");
String idCard = resultSet.getString("identityCard");
String phone = resultSet.getString("phone");
String email = resultSet.getString("email");
String address = resultSet.getString("address");
// 将获取的赋值给teacher对象
employee.setId(employeeid);
employee.setName(name);
employee.setAge(age);
employee.setGender(gender);
employee.setBornDate(bornDate);
employee.setIdentityCard(idCard);
employee.setPhone(phone);
employee.setEmail(email);
employee.setAddress(address);
}
return employee;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return null;
}
// 查询所有:将employee表中的所有数据全部查询出来,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成多个Employee对象,将多个对象存储在集合中,返回这个集合
public List<Employee> selectAll() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Employee employee = null;
List<Employee> employeeList = new ArrayList<Employee>();
String sql = "select * from employee;";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
// 查询出来多个结果,存在resultSet结果集中,遍历该结果集
while (resultSet.next()) {
int employeeid = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
Date bornDate = resultSet.getDate("bornDate");
String identityCard = resultSet.getString("identityCard");
String phone = resultSet.getString("phone");
String email = resultSet.getString("email");
String address = resultSet.getString("address");
employee = new Employee(employeeid, name, age, gender,bornDate, identityCard, phone, email, address);
employeeList.add(employee);
}
return employeeList;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return null;
}
}
5、编写EmployeeServiceImpl类(业务层代码)
package com.cxyzxc.www.examples04;
public class EmployeeServiceImpl {
/*
* 注册账号的业务逻辑:
* 1、查询你要注册的员工是否存在(根据身份证号码进行查询)
*
* 2、如果要注册的员工不存在,就注册账号
*
* 3、如果注册的员工已经存在,就返回已经注册该员工
*/
public void register(Employee employee) {
EmployeeDaoImpl employeeDaoImpl = new EmployeeDaoImpl();
// 1、查询你要注册的员工是否存在
Employee emp = employeeDaoImpl.select(employee.getIdentityCard());
// 2、如果要注册的员工不存在(emp为null),就注册账号
if (emp == null) {
employeeDaoImpl.insert(employee);
System.out.println("员工注册成功(数据插入成功)");
} else {
System.out.println("该员工已经注册(数据插入失败)");
}
}
}
6、测试注册业务
package com.cxyzxc.www.examples04;
public class TestRegister {
public static void main(String[] args) {
EmployeeServiceImpl employeeServiceImpl = new EmployeeServiceImpl();
Employee employee = new Employee("赵六", 30, "男",DateUtils.strDateToUtilDate("1992-11-29"),"340825199211291123", "13877884455", "[email protected]","安徽合肥肥西");
employeeServiceImpl.register(employee);
}
}
13.3 Service开发流程(转账业务)
13.3.1 业务需求和逻辑
(1)业务需求:
- 一个账户向另一个账户转账
(2)业务逻辑:
- 首先在数据库中查询转账账号是否存在
- 然后在数据库中查询转账账号密码是否存在
- 再验证转账账号的余额是否足够转账
- 再验证收款账号是否存在
- 执行转账操作,转账账号余额减少,收款账号余额增加(减少的金额与增加的金额相等)
13.3.2 业务实现步骤
1、创建表account
CREATE TABLE IF NOT EXISTS `account`(
`cardNo` VARCHAR(20) PRIMARY KEY COMMENT '卡号',
`password` VARCHAR(20) NOT NULL COMMENT '密码',
`name` VARCHAR(20) NOT NULL COMMENT '名称',
`balance` DOUBLE NOT NULL COMMENT '账户余额'
);
2、向account表中插入数据
INSERT INTO account VALUES('6001','123456','zhangsan',10000);
INSERT INTO account VALUES('6002','123456','lisi',5000);
3、封装实体类Account
package com.cxyzxc.www.examples05;
/**
* entity实体类Account类
*
*/
public class Account {
/** 账号 */
private String cardNo;
/** 密码 */
private String password;
/** 用户名 */
private String name;
/** 账户余额 */
private double balance;
// 无参构造方法
public Account() {
super();
}
// 有参构造方法
public Account(String cardNo, String password, String name, double balance) {
super();
this.cardNo = cardNo;
this.password = password;
this.name = name;
this.balance = balance;
}
// getXxx()/setXxx()方法
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;
}
// 重写Object类中的toString()方法
@Override
public String toString() {
return "cardNo=" + cardNo + ", password=" + password + ", name=" + name
+ ", balance=" + balance;
}
}
4、 编写AccountDaoImpl类(Dao层代码)
package com.cxyzxc.www.examples05;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AccountDaoImpl {
// 新增:插入一个Account对象到数据库中
public int insert(Account account) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "insert into account values(?,?,?,?)";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getCardNo());
preparedStatement.setString(2, account.getPassword());
preparedStatement.setString(3, account.getName());
preparedStatement.setDouble(4, account.getBalance());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 删除:根据卡号,删除账号
public int delete(String cardNo) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "delete from account where cardNo = ?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 修改
public int update(Account account) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "update account set password = ?,name = ?,balance = ? where cardNo=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getPassword());
preparedStatement.setString(2, account.getName());
preparedStatement.setDouble(3, account.getBalance());
preparedStatement.setString(4, account.getCardNo());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, null);
}
return 0;
}
// 查询单个
public Account select(String cardNo) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
connection = DBUtils.getConnection();
String sql = "select * from account where cardNo = ?";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
}
return account;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
return null;
}
// 查询所有
public List<Account> selectAll() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
List<Account> accountList = new ArrayList<Account>();
connection = DBUtils.getConnection();
String sql = "select * from account;";
try {
preparedStatement = connection.prepareStatement(sql);
// 执行SQL
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
accountList.add(account);
}
return accountList;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, preparedStatement, resultSet);
}
return null;
}
}
5、 编写AccountServiceImpl类(业务层代码)
package com.cxyzxc.www.examples05;
public class AccountServiceImpl {
/**
* 转账业务
*
* @param fromNo
* 转账人账号
* @param password
* 转账人账号密码
* @param toNo
* 收款人账号
* @param money
* 转账金额
*/
public void transfer(String fromNo, String password, String toNo,
double money) {
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
try {
// 1.验证fromNo账号是否存在
Account fromAccount = accountDaoImpl.select(fromNo);
if (fromAccount == null) {
throw new RuntimeException("卡号不存在");
}
// 2.验证fromNo的密码是否正确
if (!fromAccount.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
}
// 3.验证余额是否充足
if (fromAccount.getBalance() < money) {
throw new RuntimeException("余额不足");
}
// 4.验证toNo账号是否存在
Account toAccount = accountDaoImpl.select(toNo);
if (toAccount == null) {
throw new RuntimeException("对方卡号不存在");
}
// 5.减少fromNo账号的余额
fromAccount.setBalance(fromAccount.getBalance() - money);
accountDaoImpl.update(fromAccount);
// 6.增加toNo账号的余额
toAccount.setBalance(toAccount.getBalance() + money);
accountDaoImpl.update(toAccount);
System.out.println("转账成功");
} catch (Exception e) {
System.out.println("转账失败");
e.printStackTrace();
}
}
}
6、 测试转账业务
package com.cxyzxc.www.examples05;
public class TestTransfer {
public static void main(String[] args) {
AccountServiceImpl AccountServiceImpl = new AccountServiceImpl();
AccountServiceImpl.transfer("6001", "123456", "6002", 2000);
}
}
十四、事务
在JDBC中,获得Connection对象来处理事务–提交或回滚事务–关闭连接。其事务策略是:
- connection.setAutoCommit(false):true等价于1,false等于0
- connection.commit():手动提交事务
- connection.rollback():手动回滚事务
14.1 service层控制事务
package com.cxyzxc.www.examples06;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountServiceImpl {
/**
* 转账业务
*
* @param fromNo
* 转账人账号
* @param password
* 转账人账号密码
* @param toNo
* 收款人账号
* @param money
* 转账金额
*/
public String transfer(String fromNo, String password, String toNo,
double money) {
String result = "转账失败";
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
// 创建一个连接对象
Connection connection = null;
try {
// 获取连接对象
connection = DBUtils.getConnection();
// 开启事务,关闭事务的自动提交,改为手动提交
connection.setAutoCommit(false);
// 1.验证fromNo账号是否存在
Account fromAccount = accountDaoImpl.select(fromNo);
if (fromAccount == null) {
throw new RuntimeException("卡号不存在");
}
// 2.验证fromNo的密码是否正确
if (!fromAccount.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
}
// 3.验证余额是否充足
if (fromAccount.getBalance() < money) {
throw new RuntimeException("余额不足");
}
// 4.验证toNo账号是否存在
Account toAccount = accountDaoImpl.select(toNo);
if (toAccount == null) {
throw new RuntimeException("对方卡号不存在");
}
// 5.减少fromNo账号的余额
fromAccount.setBalance(fromAccount.getBalance() - money);
accountDaoImpl.update(fromAccount);
// 程序出现异常
@SuppressWarnings("unused")
int num = 10 / 0;
// 6.增加toNo账号的余额
toAccount.setBalance(toAccount.getBalance() + money);
accountDaoImpl.update(toAccount);
// 代码执行到这里,说明转账成功,提交事务
connection.commit();
result = "转账成功";
return result;
} catch (Exception e) {
e.printStackTrace();
try {
// 出现异常,回滚整个事务
System.out.println("出现异常,回滚整个事务,转账失败");
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtils.closeAll(connection, null, null);
}
return result;
}
}
14.2 service层控制事务失败的原因
执行这个代码,观察account表中的数据发现,当程序出现异常,转账账号余额减少了,但是收款账户余额没有增加,事务控制失败了。失败的原因是:
- AccountServiceImpl类中的connection连接对象与AccountDaoImpl类中给各个方法里的connection连接对象是不同的connection连接对象。
- AccountServiceImpl类中的connection连接对象控制事务,只能控制AccountServiceImpl类中的事务,不能控制该类之外的类里的事务
14.3 解决方案一:传递Connection
为了解决AccountServiceImpl类中的connection连接对象与AccountDaoImpl类中给各个方法里的connection连接对象是不同步的问题,可以将Connection对象通过service传递给AccountDaoImpl类中的各个方法
14.3.1 AccountDaoImpl类代码
AccountDaoImpl类中的每个方法参数列表里都要添加一个Connection类型的参数
package com.cxyzxc.www.examples07;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AccountDaoImpl {
// 新增:插入一个Account对象到数据库中
public int insert(Account account,Connection connection) {
PreparedStatement preparedStatement = null;
String sql = "insert into account values(?,?,?,?)";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getCardNo());
preparedStatement.setString(2, account.getPassword());
preparedStatement.setString(3, account.getName());
preparedStatement.setDouble(4, account.getBalance());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally{
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 删除:根据卡号,删除账号
public int delete(String cardNo,Connection connection) {
PreparedStatement preparedStatement = null;
String sql = "delete from account where cardNo = ?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally{
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 修改
public int update(Account account,Connection connection) {
PreparedStatement preparedStatement = null;
String sql = "update account set password = ?,name = ?,balance = ? where cardNo=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getPassword());
preparedStatement.setString(2, account.getName());
preparedStatement.setDouble(3, account.getBalance());
preparedStatement.setString(4, account.getCardNo());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 查询单个
public Account select(String cardNo,Connection connection) {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
String sql = "select * from account where cardNo = ?";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
}
return account;
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
// 查询所有
public List<Account> selectAll(Connection connection) {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
List<Account> accountList = new ArrayList<Account>();
String sql = "select * from account;";
try {
preparedStatement = connection.prepareStatement(sql);
// 执行SQL
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
accountList.add(account);
}
return accountList;
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
}
14.3.2 AccountServiceImpl类代码
package com.cxyzxc.www.examples07;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountServiceImpl {
/**
* 转账业务
*
* @param fromNo
* 转账人账号
* @param password
* 转账人账号密码
* @param toNo
* 收款人账号
* @param money
* 转账金额
*/
public String transfer(String fromNo, String password, String toNo,
double money) {
String result = "转账失败";
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
// 创建一个连接对象
Connection connection = null;
try {
// 获取连接对象
connection = DBUtils.getConnection();
// 开启事务,关闭事务的自动提交,改为手动提交
connection.setAutoCommit(false);
// 1.验证fromNo账号是否存在
Account fromAccount = accountDaoImpl.select(fromNo, connection);
if (fromAccount == null) {
throw new RuntimeException("卡号不存在");
}
// 2.验证fromNo的密码是否正确
if (!fromAccount.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
}
// 3.验证余额是否充足
if (fromAccount.getBalance() < money) {
throw new RuntimeException("余额不足");
}
// 4.验证toNo账号是否存在
Account toAccount = accountDaoImpl.select(toNo, connection);
if (toAccount == null) {
throw new RuntimeException("对方卡号不存在");
}
// 5.减少fromNo账号的余额
fromAccount.setBalance(fromAccount.getBalance() - money);
accountDaoImpl.update(fromAccount, connection);
// 程序出现异常
@SuppressWarnings("unused")
int num = 10 / 0;
// 6.增加toNo账号的余额
toAccount.setBalance(toAccount.getBalance() + money);
accountDaoImpl.update(toAccount, connection);
// 代码执行到这里,说明转账成功,提交事务
connection.commit();
result = "转账成功";
return result;
} catch (Exception e) {
e.printStackTrace();
try {
// 出现异常,回滚整个事务
System.out.println("出现异常,回滚整个事务,转账失败");
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtils.closeAll(connection, null, null);
}
return result;
}
}
14.3.3 测试
测试发现,这种方法可以解决service层控制事务失败的问题。
14.3.4 解决方案的弊端
(1)如果使用传递Connection,更容易造成接口污染(BadSmell)。
(2)定义接口是为了更容易更换实现,而将Connection定义在接口中(XxxDao接口,XXXDaoImpl实现XxxDao接口)中,会造成污染当前接口。因为在当前代码中连接对象叫Connection,而在其它数据库连接框架中,连接对象不叫Connection(Mybatis框架中数据库连接对象叫SqlSession,Hibernate框架中数据库连接对象叫session),这时候,你需要重新定义接口,重新传递连接对象。
14.4 解决方案二:ThreadLocal
(1)在整个线程中(单线程),存储一个共享值(Connection对象)。
(2)线程类中拥有一个类似Map的属性(),以键值对的结构<ThreadLocal对象,值>存储数据。
14.4.1 ThreadLocal应用
一个线程中所有的操作共享一个ThreadLocal,ThreadLocal里存储的是Connection连接对象,在整个操作流程中任何一个操作环节都可以设置或者获取值。
14.4.2 ThreadLocal代码实现
在DBUtils类中,将当前Connection对象添加到ThreadLocal中。其它类代码保持不变。
package com.cxyzxc.www.examples08;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 跨平台方案 注册驱动 获取连接 释放资源
*
*/
public class DBUtils {
// 读取配置文件的Map
private static final Properties PROPERTIES = new Properties();
// 声明一个ThreadLocal<Connection>对象用来存储数据库连接对象
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
static {
// 通过复用本类自带流,读取配置文件中的数据
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
try {
// 通过prop对象将流中的配置信息分隔成键值对,将配置文件内容加载到properties集合
PROPERTIES.load(is);
// 注册驱动,通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
Class.forName(PROPERTIES.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection() {
// 将当前线程中绑定的Connection对象赋值给connection变量
Connection connection = threadLocal.get();
try {
// 如果连接对象为null,则创建一个连接对象
if (connection == null) {
connection = DriverManager.getConnection(
PROPERTIES.getProperty("url"),
PROPERTIES.getProperty("username"),
PROPERTIES.getProperty("password"));
// 将创建的连接对象存储到当前线程中共享
threadLocal.set(connection);
}
} 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();
// 将connection从threadLocal中移除
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
14.4.3 AccountDaoImpl类代码
package com.cxyzxc.www.examples08;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AccountDaoImpl {
// 新增:插入一个Account对象到数据库中
public int insert(Account account) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "insert into account values(?,?,?,?)";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getCardNo());
preparedStatement.setString(2, account.getPassword());
preparedStatement.setString(3, account.getName());
preparedStatement.setDouble(4, account.getBalance());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 删除:根据卡号,删除账号
public int delete(String cardNo) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "delete from account where cardNo = ?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 修改
public int update(Account account) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "update account set password = ?,name = ?,balance = ? where cardNo=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, account.getPassword());
preparedStatement.setString(2, account.getName());
preparedStatement.setDouble(3, account.getBalance());
preparedStatement.setString(4, account.getCardNo());
// 执行SQL
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
// 查询单个
public Account select(String cardNo) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
connection = DBUtils.getConnection();
String sql = "select * from account where cardNo = ?";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, cardNo);
// 执行SQL
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
}
return account;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
// 查询所有
public List<Account> selectAll() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null;
List<Account> accountList = new ArrayList<Account>();
connection = DBUtils.getConnection();
String sql = "select * from account;";
try {
preparedStatement = connection.prepareStatement(sql);
// 执行SQL
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String cardNumber = resultSet.getString("cardNo");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
double balance = resultSet.getDouble("balance");
account = new Account(cardNumber, password, name, balance);
accountList.add(account);
}
return accountList;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
}
14.4.4 AccountServiceImpl类代码
package com.cxyzxc.www.examples08;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountServiceImpl {
/**
* 转账业务
*
* @param fromNo
* 转账人账号
* @param password
* 转账人账号密码
* @param toNo
* 收款人账号
* @param money
* 转账金额
*/
public String transfer(String fromNo, String password, String toNo,
double money) {
String result = "转账失败";
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
// 创建一个连接对象
Connection connection = null;
try {
// 获取连接对象
connection = DBUtils.getConnection();
// 开启事务,关闭事务的自动提交,改为手动提交
connection.setAutoCommit(false);
// 1.验证fromNo账号是否存在
Account fromAccount = accountDaoImpl.select(fromNo);
if (fromAccount == null) {
throw new RuntimeException("卡号不存在");
}
// 2.验证fromNo的密码是否正确
if (!fromAccount.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
}
// 3.验证余额是否充足
if (fromAccount.getBalance() < money) {
throw new RuntimeException("余额不足");
}
// 4.验证toNo账号是否存在
Account toAccount = accountDaoImpl.select(toNo);
if (toAccount == null) {
throw new RuntimeException("对方卡号不存在");
}
// 5.减少fromNo账号的余额
fromAccount.setBalance(fromAccount.getBalance() - money);
accountDaoImpl.update(fromAccount);
// 程序出现异常
@SuppressWarnings("unused")
int num = 10 / 0;
// 6.增加toNo账号的余额
toAccount.setBalance(toAccount.getBalance() + money);
accountDaoImpl.update(toAccount);
// 代码执行到这里,说明转账成功,提交事务
connection.commit();
result = "转账成功";
return result;
} catch (Exception e) {
e.printStackTrace();
try {
// 出现异常,回滚整个事务
System.out.println("出现异常,回滚整个事务,转账失败");
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtils.closeAll(connection, null, null);
}
return result;
}
}
十五、事务的封装
15.1 问题描述
(1)XXXDaoImpl类是专门用来操作数据表的,在这个类中只存在对数据表增删改查的方法,没有其它的内容。这是我们需要的。但是在XXXServiceImpl类中,既有业务需求,还有获取数据库连接对象以及释放资源的代码,在XXXServiceImpl类中,应该只有业务逻辑需求,除此,没有其它操作代码,这才是我们需要的。
(2)因此我们需要将对事务的开启、提交、回滚都封装到DBUtils工具类中。业务层调用DBUtils类中的与事务相关的代码即可。
15.2 完善工具类
package com.cxyzxc.www.examples09;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 跨平台方案 注册驱动 获取连接 释放资源
*
*/
public class DBUtils {
// 读取配置文件的Map
private static final Properties PROPERTIES = new Properties();
// 声明一个ThreadLocal<Connection>对象用来存储数据库连接对象
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
static {
// 通过复用本类自带流,读取配置文件中的数据
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
try {
// 通过prop对象将流中的配置信息分隔成键值对,将配置文件内容加载到properties集合
PROPERTIES.load(is);
// 注册驱动,通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
Class.forName(PROPERTIES.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection() {
// 将当前线程中绑定的Connection对象赋值给connection变量
Connection connection = threadLocal.get();
try {
// 如果连接对象为null,则创建一个连接对象
if (connection == null) {
connection = DriverManager.getConnection(
PROPERTIES.getProperty("url"),
PROPERTIES.getProperty("username"),
PROPERTIES.getProperty("password"));
// 将创建的连接对象存储到当前线程中共享
threadLocal.set(connection);
}
} 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();
// 将connection从threadLocal中移除
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// 3、开启事务
public static void startTransaction() {
Connection connection = null;
try {
connection = getConnection();
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 4、提交事务
public static void commitTransaction() {
Connection connection = getConnection();
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, null, null);
}
}
// 5、回滚事务
public static void rollbackTransaction() {
Connection connection = getConnection();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, null, null);
}
}
}
15.3 AccountServiceImpl类代码修改
package com.cxyzxc.www.examples09;
public class AccountServiceImpl {
/**
* 转账业务
*
* @param fromNo
* 转账人账号
* @param password
* 转账人账号密码
* @param toNo
* 收款人账号
* @param money
* 转账金额
*/
public String transfer(String fromNo, String password, String toNo,
double money) {
String result = "转账失败";
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
try {
// 开启事务,关闭事务的自动提交,改为手动提交
DBUtils.startTransaction();
// 1.验证fromNo账号是否存在
Account fromAccount = accountDaoImpl.select(fromNo);
if (fromAccount == null) {
throw new RuntimeException("卡号不存在");
}
// 2.验证fromNo的密码是否正确
if (!fromAccount.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
}
// 3.验证余额是否充足
if (fromAccount.getBalance() < money) {
throw new RuntimeException("余额不足");
}
// 4.验证toNo账号是否存在
Account toAccount = accountDaoImpl.select(toNo);
if (toAccount == null) {
throw new RuntimeException("对方卡号不存在");
}
// 5.减少fromNo账号的余额
fromAccount.setBalance(fromAccount.getBalance() - money);
accountDaoImpl.update(fromAccount);
// 程序出现异常
@SuppressWarnings("unused")
int num = 10 / 0;
// 6.增加toNo账号的余额
toAccount.setBalance(toAccount.getBalance() + money);
accountDaoImpl.update(toAccount);
// 代码执行到这里,说明转账成功,提交事务
DBUtils.commitTransaction();
result = "转账成功";
return result;
} catch (Exception e) {
e.printStackTrace();
// 出现异常,回滚整个事务
System.out.println("出现异常,回滚整个事务,转账失败");
DBUtils.rollbackTransaction();
}
return result;
}
}
十六、三层架构
16.1 什么是三层
(1)表示层(View)
- 命名:XxxView
- 职责:收集用户的数据和需求、数据
(2)业务逻辑层(service)
- 命名:XxxServiceImpl
- 职责:数据加工处理、调用DAO完成业务实现、控制事务
(3)数据访问层(Dao)
- 命名:XxxDaoImpl
- 职责:向业务层提供数据,将业务层加工后的数据同步到数据库
16.2 三层架构项目搭建步骤
16.2.1 项目环境搭建
1)新建一个项目,在项目中创建lib文件夹,将MySQL数据库jar包放在lib文件夹中,配置环境。
2)在src文件夹下面创建db.properties文件,编写数据库driver、url、user、password信息。
3)创建三层需要的各个包。
(1)utils包:存放工具类(DBUtils类、DateUtils类)
(2)entity包:存放实体类(Xxx.java)
(3)dao包:存放DAO接口
impl包:存放DAO接口实现类
(4)service包:存放service接口
impl:存放service接口实现类
(5)view包:存放程序启动类或测试类(main)
16.2.2 创建book表
16.2.2.1 创建表
CREATE TABLE IF NOT EXISTS `book`(
`bid` INT PRIMARY KEY AUTO_INCREMENT COMMENT '图书编号',
`isbn` VARCHAR(20) UNIQUE NOT NULL COMMENT '国际标准书号',
`name` VARCHAR(20) NOT NULL COMMENT '书名',
`author` VARCHAR(20) NOT NULL COMMENT '作者',
`press` VARCHAR(20) NOT NULL COMMENT '出版社',
`price` DOUBLE NOT NULL COMMENT '价格',
`classification` VARCHAR(20) NOT NULL COMMENT '分类'
);
16.2.2.2 向表中插入数据
INSERT INTO `book`(`bid`,`isbn`,`name`,`author`,`press`,`price`,`classification`)
VALUES
(1001,'978-7-5170-7654-4','SQL从入门到精通','张三','中国水利水电出版社',79.80,'数据库');
INSERT INTO `book`(`bid`,`isbn`,`name`,`author`,`press`,`price`,`classification`)
VALUES
(1002,'976-9-5245-7633-5','java从入门到精通','李四','清华大学出版社',99.80,'程序设计');
16.2.3 创建entity实体类Book
package com.cxyzxc.www.entity;
import java.util.Date;
/**
* entity实体类Booke类
*
*/
public class Book {
/** 图书编号 */
private int bid;
/** 国际标准书号 */
private String isbn;
/** 书名 */
private String name;
/** 作者 */
private String author;
/** 出版社 */
private String press;
/** 价格 */
private double price;
/** 分类 */
private String classification;
/** 出版日期 */
private Date pubdate;
public Book() {
super();
}
public Book(String isbn, String name, String author, String press,
double price, String classification, Date pubdate) {
super();
this.isbn = isbn;
this.name = name;
this.author = author;
this.press = press;
this.price = price;
this.classification = classification;
this.pubdate = pubdate;
}
public Book(int bid, String isbn, String name, String author, String press,
double price, String classification, Date pubdate) {
super();
this.bid = bid;
this.isbn = isbn;
this.name = name;
this.author = author;
this.press = press;
this.price = price;
this.classification = classification;
this.pubdate = pubdate;
}
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getClassification() {
return classification;
}
public void setClassification(String classification) {
this.classification = classification;
}
public Date getPubdate() {
return pubdate;
}
public void setPubdate(Date pubdate) {
this.pubdate = pubdate;
}
@Override
public String toString() {
return "Book [bid=" + bid + ", isbn=" + isbn + ", name=" + name
+ ", author=" + author + ", press=" + press + ", price="
+ price + ", classification=" + classification + ", pubdate="
+ pubdate + "]";
}
}
16.2.4 创建BookDao接口
package com.cxyzxc.www.dao;
import java.util.List;
import com.cxyzxc.www.entity.Book;
/**
* 定义BookDao接口,接口中定义对book表增删改查的方法
*
*/
public interface BookDao {
//增
int insert(Book book);
//删
int delete(int bid);
//改
int update(Book book);
//查单个
Book selectOne(int bid);
//查所有
List<Book> selectAll();
}
16.2.5 创建BookDaoImpl实现类
package com.cxyzxc.www.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.cxyzxc.www.dao.BookDao;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.utils.DBUtils;
import com.cxyzxc.www.utils.DateUtils;
/**
* 定义BookDaoImpl类,实现BookDao接口,重写接口中的增删改查方法
*
*/
public class BookDaoImpl implements BookDao {
@Override
public int insert(Book book) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "INSERT INTO `book`(`isbn`,`name`,`author`,`press`,`price`,`classification`,`pubdate`)VALUES(?,?,?,?,?,?,?);";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, book.getIsbn());
preparedStatement.setString(2, book.getName());
preparedStatement.setString(3, book.getAuthor());
preparedStatement.setString(4, book.getPress());
preparedStatement.setDouble(5, book.getPrice());
preparedStatement.setString(6, book.getClassification());
preparedStatement.setDate(7,
DateUtils.utilDateToSqlDate(book.getPubdate()));
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int delete(int bid) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "DELETE FROM `book` WHERE `bid`=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setInt(1, bid);
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int update(Book book) {
Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DBUtils.getConnection();
String sql = "UPDATE `book` SET `isbn`=?,`name`=?,`author`=?,`press`=?,`price`=?,`classification`=?,`pubdate`=? WHERE `bid`=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setString(1, book.getIsbn());
preparedStatement.setString(2, book.getName());
preparedStatement.setString(3, book.getAuthor());
preparedStatement.setString(4, book.getPress());
preparedStatement.setDouble(5, book.getPrice());
preparedStatement.setString(6, book.getClassification());
preparedStatement.setDate(7,
DateUtils.utilDateToSqlDate(book.getPubdate()));
preparedStatement.setDouble(8, book.getBid());
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Book selectOne(int bid) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Book book = null;
connection = DBUtils.getConnection();
String sql = "Select * FROM `book` WHERE `bid`=?;";
try {
preparedStatement = connection.prepareStatement(sql);
// 绑定参数
preparedStatement.setInt(1, bid);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
int bookid = resultSet.getInt(1);
String isbn = resultSet.getString(2);
String name = resultSet.getString(3);
String author = resultSet.getString(4);
String press = resultSet.getString(5);
double price = resultSet.getDouble(6);
String classification = resultSet.getString(7);
Date pubdate = resultSet.getDate(8);
book = new Book(bookid, isbn, name, author, press, price,
classification, pubdate);
}
return book;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Book> selectAll() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Book book = null;
List<Book> bookList = new ArrayList<Book>();
connection = DBUtils.getConnection();
String sql = "Select * FROM `book`;";
try {
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
int bookid = resultSet.getInt(1);
String isbn = resultSet.getString(2);
String name = resultSet.getString(3);
String author = resultSet.getString(4);
String press = resultSet.getString(5);
double price = resultSet.getDouble(6);
String classification = resultSet.getString(7);
Date pubdate = resultSet.getDate(8);
book = new Book(bookid, isbn, name, author, press, price,
classification, pubdate);
bookList.add(book);
}
return bookList;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
16.2.6 创建BookService接口
package com.cxyzxc.www.service;
import java.util.List;
import com.cxyzxc.www.entity.Book;
/**
* 定义BookService接口,接口中定义业务逻辑方法
*
*/
public interface BookService {
//添加图书
int addBook(Book book);
//删除图书
int deleteBook(int bid);
//修改图书
int updateBook(Book book);
//查询一本图书
Book selectOne(int bid);
//查询所有图书
List<Book> selectAll();
}
16.2.7 创建BookServiceImpl实现类
package com.cxyzxc.www.service.impl;
import java.util.List;
import com.cxyzxc.www.dao.BookDao;
import com.cxyzxc.www.dao.impl.BookDaoImpl;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.service.BookService;
/**
* 定义BookServiceImpl类,实现BookService接口,重写BookService接口中的所有方法
*
*/
public class BookServiceImpl implements BookService {
BookDao bookDao = new BookDaoImpl();
@Override
public int addBook(Book book) {
// 首先查询一下插入的图书在数据库中是否存在
Book book2 = bookDao.selectOne(book.getBid());
if (book2 == null) {
return bookDao.insert(book);
} else {
System.out.println("插入的图书已经存在,插入失败");
}
return 0;
}
@Override
public int deleteBook(int bid) {
// 查询要删除的图书是否存在
Book book2 = bookDao.selectOne(bid);
if (book2 == null) {
System.out.println("删除的图书不存在,无法删除");
} else {
return bookDao.delete(bid);
}
return 0;
}
@Override
public int updateBook(Book book) {
// 查询要修改的图书是否存在
Book book2 = bookDao.selectOne(book.getBid());
if (book2 == null) {
System.out.println("你要修改的图书不存在");
} else {
return bookDao.update(book);
}
return 0;
}
@Override
public Book selectOne(int bid) {
Book book2 = bookDao.selectOne(bid);
return book2;
}
@Override
public List<Book> selectAll() {
List<Book> bookList = bookDao.selectAll();
return bookList;
}
}
16.2.8 编写测试类
16.2.8.1 测试增加数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.service.BookService;
import com.cxyzxc.www.service.impl.BookServiceImpl;
import com.cxyzxc.www.utils.DateUtils;
public class Test01InsertBook {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
// 添加图书
Book book = new Book("978-9-9456-3286-9", "JSP从入门到精通", "李二狗", "邮电出版社",129, "编程设计", DateUtils.strDateToUtilDate("2022-01-13"));
int result = bookService.addBook(book);
if (result == 1) {
System.out.println("图书添加成功");
} else {
System.out.println("图书添加失败");
}
}
}
16.2.8.2 测试删除数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.service.BookService;
import com.cxyzxc.www.service.impl.BookServiceImpl;
public class Test02DeleteBook {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
// 删除图书
int result = bookService.deleteBook(1003);
if (result == 1) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
}
16.2.8.3 测试修改数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.service.BookService;
import com.cxyzxc.www.service.impl.BookServiceImpl;
import com.cxyzxc.www.utils.DateUtils;
public class Test03UpdateBook {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
// //修改图书
Book book = new Book(1002, "976-9-5245-7633-5", "JSP从入门到放弃", "李四","清华大学出版社", 109.8, "编程设计",DateUtils.strDateToUtilDate("2022-10-13"));
int result = bookService.updateBook(book);
if (result == 1) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
}
}
16.2.8.4 测试查询单个
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.service.BookService;
import com.cxyzxc.www.service.impl.BookServiceImpl;
public class Test04SelectOneBook {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
Book book = bookService.selectOne(1003);
if (book == null) {
System.out.println("没有你要查找的图书");
} else {
System.out.println(book);
}
}
}
16.2.8.4 测试查询所有
package com.cxyzxc.www.view;
import java.util.List;
import com.cxyzxc.www.entity.Book;
import com.cxyzxc.www.service.BookService;
import com.cxyzxc.www.service.impl.BookServiceImpl;
public class Test05SelectAllBook {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
List<Book> books = bookService.selectAll();
if (books.isEmpty()) {
System.out.println("数据库里没有书的数据");
} else {
for (int i = 0; i < books.size(); i++) {
System.out.println(books.get(i));
}
}
}
}
十七、DaoUtils(Object类型方法)
在Dao层的DaoImpl类中,对数据表进行的增、删、改、查操作方法中存在很多相同的代码,可以将这些相同的代码抽取出来封装到一个类中,形成DaoUtils工具类,实现复用。以查询teacher表为例。
17.1 commonsUpdae方法
该方法是对数据表进行增、删、改的公共方法。
// 增、删、改三个方法封装成一个方法
public int commonsUpdate(String sql, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
17.2 commonsSelect方法
该方法是对数据表进行查询的公共方法,可以查询一条数据,也可以查询多条数据。不管是查询一条数据还是查询多条数据,都将查询到的数据封装到Object类型的集合中。
public List<Object> commonsSelect(String sql,RowMapper rowMapper, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
List<Object> objectList = new ArrayList<Object>();
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Object object = rowMapper.getRow(resultSet);
objectList.add(object);
}
return objectList;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
17.3 RowMapper类封装resultSet结果集
使用查询方法从表中查询出来的结果存储在ResultSet结果集中,需要从ResultSet结果集中遍历出数据封装成对应对象,然后将封装出来的对象返回给DaoImpl类使用。这个封装的过程由RowMapper类完成。
package com.cxyzxc.www.examples01;
/**
* 数据封装类,专门用来处理查询返回的resultSet结果集
*
* 针对每一个实体类,封装一个RowMapper类
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class RowMapper {
public static Object getRow(ResultSet resultSet){
Teacher teacher = null;
try {
//返回的结果集中有哪些字段,RowMapper类是知道的,因为他是实体类的封装类
int tid = resultSet.getInt("tid");
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");
teacher = new Teacher(tid, name, age, bornDate, email, address);
return teacher;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
17.4 综合案例
综合案例完全按照三层架构实现,创建不同的包存放不同的接口、实现类、工具类、测试类等代码。使用数据库中的teacher表来完成综合案例。
17.4.1 com.cxyzxc.www.utils包
该包用来存放项目开发所需要的数据库连接工具类DBUtils类、日期时间转换工具类DateUtils类,数据库操作工具类DaoUtils类
17.4.1.1 DaoUtils工具类完整代码
package com.cxyzxc.www.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.cxyzxc.www.advanced.RowMapper;
public class DaoUtils {
// 增、删、改三个方法封装成一个方法
public int commonsUpdate(String sql, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
public List<Object> commonsSelect(String sql,RowMapper rowMapper, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
List<Object> objectList = new ArrayList<Object>();
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Object object = rowMapper.getRow(resultSet);
objectList.add(object);
}
return objectList;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(null, preparedStatement, resultSet);
}
return null;
}
}
17.4.1.2 DBUtils工具类完整代码
package com.cxyzxc.www.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 跨平台方案 注册驱动 获取连接 释放资源
*
* @author 程序员张小厨
*
*/
public class DBUtils {
// 读取配置文件的Map
private static final Properties PROPERTIES = new Properties();
// 声明一个ThreadLocal<Connection>对象用来存储数据库连接对象
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
static {
// 通过复用本类自带流,读取配置文件中的数据
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
try {
// 通过prop对象将流中的配置信息分隔成键值对,将配置文件内容加载到properties集合
PROPERTIES.load(is);
// 注册驱动,通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
Class.forName(PROPERTIES.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection() {
// 将当前线程中绑定的Connection对象赋值给connection变量
Connection connection = threadLocal.get();
try {
// 如果连接对象为null,则创建一个连接对象
if (connection == null) {
connection = DriverManager.getConnection(
PROPERTIES.getProperty("url"),
PROPERTIES.getProperty("username"),
PROPERTIES.getProperty("password"));
// 将创建的连接对象存储到当前线程中共享
threadLocal.set(connection);
}
} 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();
// 将connection从threadLocal中移除
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// 3、开启事务
public static void startTransaction() {
Connection connection = null;
try {
connection = getConnection();
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 4、提交事务
public static void commitTransaction() {
Connection connection = getConnection();
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, null, null);
}
}
// 5、回滚事务
public static void rollbackTransaction() {
Connection connection = getConnection();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(connection, null, null);
}
}
}
17.4.1.3 DateUtils工具类完整代码
package com.cxyzxc.www.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 日期时间工具类DateUtils
*/
public class DateUtils {
private static final SimpleDateFormat SIMPLEDATEFORMAT = new SimpleDateFormat("yyyy-MM-dd");
// 字符串转换为java.util.Date类型日期时间
public static java.util.Date strDateToUtilDate(String strDate) {
try {
return SIMPLEDATEFORMAT.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
// java.util.Date类型日期时间转换为java.sql.Date类型日期时间
public static java.sql.Date utilDateToSqlDate(java.util.Date date) {
// long date.getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT以来此 Date对象表示的毫秒数
return new java.sql.Date(date.getTime());
}
// java.util.Date类转换为字符串类型
public static String utilDateToString(java.util.Date date) {
return SIMPLEDATEFORMAT.format(date);
}
}
17.4.2 com.cxyzxc.www.entity包
该包用来存储实体类,根据teacher表创建实体类Teacher类
package com.cxyzxc.www.entity;
import java.util.Date;
public class Teacher {
/** 教师编号 */
private int tid;
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 出生日期 */
private Date bornDate;
/** 邮箱 */
private String email;
/** 住址 */
private String address;
// 无参构造方法
public Teacher() {
super();
}
// 有参构造方法
public Teacher(String name, int age, Date bornDate, String email,
String address) {
super();
this.name = name;
this.age = age;
this.bornDate = bornDate;
this.email = email;
this.address = address;
}
public Teacher(int tid, String name, int age, Date bornDate, String email,
String address) {
super();
this.tid = tid;
this.name = name;
this.age = age;
this.bornDate = bornDate;
this.email = email;
this.address = address;
}
// getXxx()/setXxx()方法
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int 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;
}
// 重写Object类中的toString()方法
@Override
public String toString() {
return "tid=" + tid + ", name=" + name + ", age=" + age + ", bornDate="
+ bornDate + ", email=" + email + ", address=" + address;
}
}
17.4.3 com.cxyzxc.www.advanced包
该包中存放RowMapper接口,用来约束封装对象的ORM
package com.cxyzxc.www.advanced;
import java.sql.ResultSet;
/**
* 该接口用来约束封装对象的ORM
*
*/
public interface RowMapper {
Object getRow(ResultSet resultSet);
}
17.4.4 com.cxyzxc.www.advanced.impl包
package com.cxyzxc.www.advanced.impl;
/**
* 数据封装类,专门用来处理查询返回的resultSet结果集
*
* 针对每一个实体类,封装一个RowMapper类
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import com.cxyzxc.www.advanced.RowMapper;
import com.cxyzxc.www.entity.Teacher;
public class TeacherRowMapper implements RowMapper {
@Override
public Object getRow(ResultSet resultSet) {
Teacher teacher = null;
try {
// 返回的结果集中有哪些字段,RowMapper类是知道的,因为他是实体类的封装类
int tid = resultSet.getInt("tid");
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");
teacher = new Teacher(tid, name, age, bornDate, email, address);
return teacher;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
17.4.5 com.cxyzxc.www.dao包
该包用来存放操作数据库的接口
package com.cxyzxc.www.dao;
import java.util.List;
import com.cxyzxc.www.entity.Teacher;
public interface TeacherDao {
//增
int insert(Teacher teacher);
//删
int delete(int tid);
//改
int update(Teacher teacher);
//查单个
Teacher selectOne(int tid);
//查所有
List<Teacher> selectAll();
}
17.4.6 com.cxyzxc.www.dao.impl包
该包用来存放数据库操作接口的实现类
package com.cxyzxc.www.dao.impl;
import java.util.ArrayList;
import java.util.List;
import com.cxyzxc.www.advanced.RowMapper;
import com.cxyzxc.www.advanced.impl.TeacherRowMapper;
import com.cxyzxc.www.dao.TeacherDao;
import com.cxyzxc.www.entity.Teacher
*/
public class TeacherDaoImpl implements TeacherDao {
/*
* (1)该类中提供对teacher表进行增、删、改、查单个、查所有5个方法。
*
* (2)该类中的代码只做数据库访问操作,不做任何业务逻辑操作。
*
* (3)该类只对数据库一张表进行操作,从而实现复用
*/
DaoUtils daoUtils = new DaoUtils();
RowMapper rowMapper = new TeacherRowMapper();
// 新增:向teacher表中插入一条数据(一条数据对应一个Teacher对象),插入成功,返回一个受影响行数值(int类型)
@Override
public int insert(Teacher teacher) {
String sql = "insert into `teacher`(name,age,bornDate,email,address) values(?,?,?,?,?);";
// 赋值
Object[] args = { teacher.getName(), teacher.getAge(),
teacher.getBornDate(), teacher.getEmail(), teacher.getAddress() };
return daoUtils.commonsUpdate(sql, args);
}
// 删除:根据教师tid删除一条数据,删除成功,返回一个受影响行数值(int类型)
@Override
public int delete(int tid) {
String sql = "delete from teacher where tid = ?;";
return daoUtils.commonsUpdate(sql, tid);
}
// 修改:修改teacher表中的数据,可能对任意的一个字段进行修改,所以方法中直接传递一个对象进行修改,修改成功,返回一个受影响行数值(int类型)
@Override
public int update(Teacher teacher) {
String sql = "update teacher set name = ?,age = ?,bornDate = ?,email = ?,address = ? where tid = ?;";
Object[] args = { teacher.getName(), teacher.getAge(),
teacher.getBornDate(), teacher.getEmail(),
teacher.getAddress(), teacher.getTid() };
return daoUtils.commonsUpdate(sql, args);
}
// 查询单个:根据教师tid查询一条数据,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成一个Teacher对象,将该对象返回
@Override
public Teacher selectOne(int tid) {
String sql = "select * from teacher where tid = ?;";
List<Object> objectList = daoUtils.commonsSelect(sql, rowMapper, tid);
if (objectList.size() == 1) {
Teacher teacher = (Teacher) objectList.get(0);
return teacher;
} else {
return null;
}
}
// 查询所有:将teacher表中的所有数据全部查询出来,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成多个Teacher对象,将多个对象存储在集合中,返回这个集合
@Override
public List<Teacher> selectAll() {
List<Teacher> teacherList = new ArrayList<Teacher>();
String sql = "select * from teacher;";
DaoUtils daoUtils = new DaoUtils();
Object[] args = null;
List<Object> objectList = daoUtils.commonsSelect(sql, rowMapper, args);
for (int i = 0; i < objectList.size(); i++) {
teacherList.add((Teacher) objectList.get(i));
}
return teacherList;
}
}
17.4.7 com.cxyzxc.www.service包
该包用来存储业务层接口代码
package com.cxyzxc.www.service;
import java.util.List;
import com.cxyzxc.www.entity.Teacher;
public interface TeacherService {
//添加老师
int addTeacher(Teacher teacher);
//删除老师
int deleteTeacher(int tid);
//修改老师
int updateTeacher(Teacher teacher);
//查询一个老师
Teacher selectOne(int tid);
//查询所有老师
List<Teacher> selectAll();
}
17.4.8 com.cxyzxc.www.service.impl包
该包用来存储service层实现类代码
package com.cxyzxc.www.service.impl;
import java.util.List;
import com.cxyzxc.www.dao.impl.TeacherDaoImpl;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.service.TeacherService;
public class TeacherServiceImpl implements TeacherService {
@Override
public int addTeacher(Teacher teacher) {
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
Teacher teacher2 = teacherDaoImpl.selectOne(teacher.getTid());
if (teacher2 == null) {
return teacherDaoImpl.insert(teacher);
} else {
System.out.println("老师已存在");
}
return 0;
}
@Override
public int deleteTeacher(int tid) {
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
Teacher teacher2 = teacherDaoImpl.selectOne(tid);
if (teacher2 == null) {
System.out.println("你要删除的老师不存在,无法删除");
} else {
return teacherDaoImpl.delete(tid);
}
return 0;
}
@Override
public int updateTeacher(Teacher teacher) {
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
Teacher teacher2 = teacherDaoImpl.selectOne(teacher.getTid());
if (teacher2 == null) {
System.out.println("你要修改的老师不存在,无法修改");
} else {
return teacherDaoImpl.update(teacher);
}
return 0;
}
@Override
public Teacher selectOne(int tid){
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
Teacher teacher =teacherDaoImpl.selectOne(tid);
return teacher;
}
@Override
public List<Teacher> selectAll(){
TeacherDaoImpl teacherDaoImpl = new TeacherDaoImpl();
return teacherDaoImpl.selectAll();
}
}
17.4.9 com.cxy.zxc.view包
该包用来存储测试类
17.4.9.1 测试插入数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.service.TeacherService;
import com.cxyzxc.www.service.impl.TeacherServiceImpl;
import com.cxyzxc.www.utils.DateUtils;
public class TestTeacherServiceImpl01Insert {
public static void main(String[] args) {
TeacherService teacherService = new TeacherServiceImpl();
Teacher teacher = new Teacher(1004, "王五", 30, DateUtils.strDateToUtilDate("1992-10-07"), "[email protected]", "安徽合肥庐阳区");
int result =teacherService.addTeacher(teacher);
if(result!=0){
System.out.println("老师添加成功");
}
}
}
17.4.9.2 测试删除数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.service.TeacherService;
import com.cxyzxc.www.service.impl.TeacherServiceImpl;
public class TestTeacherServiceImpl02Delete {
public static void main(String[] args) {
TeacherService teacherService = new TeacherServiceImpl();
int result =teacherService.deleteTeacher(1004);
if(result!=0){
System.out.println("删除成功");
}
}
}
17.4.9.3 测试修改数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.service.TeacherService;
import com.cxyzxc.www.service.impl.TeacherServiceImpl;
import com.cxyzxc.www.utils.DateUtils;
public class TestTeacherServiceImpl03Update {
public static void main(String[] args) {
TeacherService teacherService = new TeacherServiceImpl();
Teacher teacher = new Teacher(1003, "王五", 30,
DateUtils.strDateToUtilDate("1992-08-07"),
"[email protected]", "安徽合肥政务区");
int result = teacherService.updateTeacher(teacher);
if(result!=0){
System.out.println("修改成功");
}
}
}
17.4.9.4 测试查询一条数据
package com.cxyzxc.www.view;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.service.TeacherService;
import com.cxyzxc.www.service.impl.TeacherServiceImpl;
public class TestTeacherServiceImpl04SelectOne {
public static void main(String[] args) {
TeacherService teacherService = new TeacherServiceImpl();
Teacher teacher = teacherService.selectOne(1002);
if (teacher != null) {
System.out.println(teacher);
} else {
System.out.println("你查询的老师不存在");
}
}
}
17.4.9.5 测试查询所有数据
package com.cxyzxc.www.view;
import java.util.List;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.service.TeacherService;
import com.cxyzxc.www.service.impl.TeacherServiceImpl;
public class TestTeacherServiceImpl05SelectAll {
public static void main(String[] args) {
TeacherService teacherService = new TeacherServiceImpl();
List<Teacher> listTeacher = teacherService.selectAll();
for (int i = 0; i < listTeacher.size(); i++) {
System.out.println(listTeacher.get(i));
}
}
}
十八、DaoUtils(泛型类型方法)
18.1 commonsUpdate方法
该方法是对数据表进行增、删、改的公共方法。与17.1小节中的代码一样,不再赘述。
18.2 commonsSelect方法
该方法是对数据表进行查询的公共方法,可以查询一条数据,也可以查询多条数据。不管是查询一条数据还是查询多条数据,都将查询到的数据封装到泛型类型的集合中。
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<T>();
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
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;
}
18.3 RowMapper类封装resultSet结果集
18.3.1 RowMapper接口:
package com.cxyzxc.www.advanced;
import java.sql.ResultSet;
/**
* 该接口用来约束封装对象的ORM
*
*/
public interface RowMapper<T> {
T getRow(ResultSet resultSet);
}
18.3.2 RowMapper接口实现类:
package com.cxyzxc.www.advanced.impl;
/**
* 数据封装类,专门用来处理查询返回的resultSet结果集
*
* 针对每一个实体类,封装一个RowMapper类
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import com.cxyzxc.www.advanced.RowMapper;
import com.cxyzxc.www.entity.Teacher;
public class TeacherRowMapper implements RowMapper<Teacher> {
@Override
public Teacher getRow(ResultSet resultSet) {
Teacher teacher = null;
try {
// 返回的结果集中有哪些字段,RowMapper类是知道的,因为他是实体类的封装类
int tid = resultSet.getInt("tid");
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");
teacher = new Teacher(tid, name, age, bornDate, email, address);
return teacher;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
18.4 综合案例
综合案例完全按照三层架构实现,创建不同的包存放不同的接口、实现类、工具类、测试类等代码。使用数据库中的teacher表来完成综合案例。
18.4.1 com.cxyzxc.www.utils包
该包用来存放项目开发所需要的数据库连接工具类DBUtils类、日期时间转换工具类DateUtils类,数据库操作工具类DaoUtils类
18.4.1.1 DaoUtils工具类完整代码
package com.cxyzxc.www.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.cxyzxc.www.advanced.RowMapper;
public class DaoUtils<T> {
// 增、删、改三个方法封装成一个方法
public int commonsUpdate(String sql, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(null, preparedStatement, null);
}
return 0;
}
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<T>();
// 获取数据库连接对象
connection = DBUtils.getConnection();
try {
// 获取SQL语句发送对象
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
// 绑定参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
// 执行SQL语句
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;
}
}
18.4.1.2 DBUtils工具类完整代码
该类与17.4.1.2小节中的代码一样,不再赘述。
18.4.1.3 DateUtils工具类完整代码
该类与17.4.1.3小节中的代码一样,不再赘述。
18.4.2 com.cxyzxc.www.entity包
该包用来存储实体类,根据teacher表创建实体类Teacher类,与17.4.2小节中的代码一样,不再赘述。
18.4.3 com.cxyzxc.www.advanced包
该包中存放RowMapper接口,用来约束封装对象的ORM
package com.cxyzxc.www.advanced;
import java.sql.ResultSet;
/**
* 该接口用来约束封装对象的ORM
*
*/
public interface RowMapper<T> {
T getRow(ResultSet resultSet);
}
18.4.4 com.cxyzxc.www.advanced.impl包
package com.cxyzxc.www.advanced.impl;
/**
* 数据封装类,专门用来处理查询返回的resultSet结果集
*
* 针对每一个实体类,封装一个RowMapper类
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import com.cxyzxc.www.advanced.RowMapper;
import com.cxyzxc.www.entity.Teacher;
public class TeacherRowMapper implements RowMapper<Teacher> {
@Override
public Teacher getRow(ResultSet resultSet) {
Teacher teacher = null;
try {
// 返回的结果集中有哪些字段,RowMapper类是知道的,因为他是实体类的封装类
int tid = resultSet.getInt("tid");
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");
teacher = new Teacher(tid, name, age, bornDate, email, address);
return teacher;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
18.4.5 com.cxyzxc.www.dao包
该包用来存放操作数据库的接口
package com.cxyzxc.www.dao;
import java.util.List;
import com.cxyzxc.www.entity.Teacher;
public interface TeacherDao {
//增
int insert(Teacher teacher);
//删
int delete(int tid);
//改
int update(Teacher teacher);
//查单个
Teacher selectOne(int tid);
//查所有
List<Teacher> selectAll();
}
18.4.6 com.cxyzxc.www.dao.impl包
该包用来存放数据库操作接口的实现类
package com.cxyzxc.www.dao.impl;
import java.util.ArrayList;
import java.util.List;
import com.cxyzxc.www.advanced.RowMapper;
import com.cxyzxc.www.advanced.impl.TeacherRowMapper;
import com.cxyzxc.www.dao.TeacherDao;
import com.cxyzxc.www.entity.Teacher;
import com.cxyzxc.www.utils.DaoUtils;
/**
*
*/
public class TeacherDaoImpl implements TeacherDao {
/*
* (1)该类中提供对teacher表进行增、删、改、查单个、查所有5个方法。
*
* (2)该类中的代码只做数据库访问操作,不做任何业务逻辑操作。
*
* (3)该类只对数据库一张表进行操作,从而实现复用
*/
DaoUtils<Teacher> daoUtils = new DaoUtils<Teacher>();
RowMapper<Teacher> rowMapper = new TeacherRowMapper();
// 新增:向teacher表中插入一条数据(一条数据对应一个Teacher对象),插入成功,返回一个受影响行数值(int类型)
@Override
public int insert(Teacher teacher) {
String sql = "insert into `teacher`(name,age,bornDate,email,address) values(?,?,?,?,?);";
// 赋值
Object[] args = { teacher.getName(), teacher.getAge(),
teacher.getBornDate(), teacher.getEmail(), teacher.getAddress() };
return daoUtils.commonsUpdate(sql, args);
}
// 删除:根据教师tid删除一条数据,删除成功,返回一个受影响行数值(int类型)
@Override
public int delete(int tid) {
String sql = "delete from teacher where tid = ?;";
return daoUtils.commonsUpdate(sql, tid);
}
// 修改:修改teacher表中的数据,可能对任意的一个字段进行修改,所以方法中直接传递一个对象进行修改,修改成功,返回一个受影响行数值(int类型)
@Override
public int update(Teacher teacher) {
String sql = "update teacher set name = ?,age = ?,bornDate = ?,email = ?,address = ? where tid = ?;";
Object[] args = { teacher.getName(), teacher.getAge(),
teacher.getBornDate(), teacher.getEmail(),
teacher.getAddress(), teacher.getTid() };
return daoUtils.commonsUpdate(sql, args);
}
// 查询单个:根据教师tid查询一条数据,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成一个Teacher对象,将该对象返回
@Override
public Teacher selectOne(int tid) {
String sql = "select * from teacher where tid = ?;";
List<Teacher> objectList = daoUtils.commonsSelect(sql, rowMapper, tid);
if (objectList.size() == 1) {
Teacher teacher = (Teacher) objectList.get(0);
return teacher;
} else {
return null;
}
}
// 查询所有:将teacher表中的所有数据全部查询出来,查询成功返回一个结果集(ResultSet类型),从结果集中取出元素,封装成多个Teacher对象,将多个对象存储在集合中,返回这个集合
@Override
public List<Teacher> selectAll() {
List<Teacher> teacherList = new ArrayList<Teacher>();
String sql = "select * from teacher;";
Object[] args = null;
List<Teacher> list = daoUtils.commonsSelect(sql, rowMapper, args);
for (int i = 0; i < list.size(); i++) {
teacherList.add(list.get(i));
}
return teacherList;
}
}
18.4.7 com.cxyzxc.www.service包
该包用来存储业务层接口代码,与17.4.7小节代码一直,这里不再赘述。
18.4.8 com.cxyzxc.www.service.impl包
该包用来存储service层实现类代码,与17.4.8小节中代码一致,这里不再赘述。
18.4.9 com.cxy.zxc.view包
该包用来存储测试类
18.4.9.1 测试插入数据
与17.4.9.1小节代码一致,不再赘述。
18.4.9.2 测试删除数据
与17.4.9.2小节代码一致,不再赘述。
18.4.9.3 测试修改数据
与17.4.9.3小节代码一致,不再赘述。
18.4.9.4 测试查询一条数据
与17.4.9.4小节代码一致,不再赘述。
18.4.9.5 测试查询所有数据
与17.4.9.5小节代码一致,不再赘述。
十九、Druid连接池
19.1 连接池思想
在程序初始化时,提前创建好指定数量的数据库连接对象存储在“池子”中(这个池子称为“连接池”),当需要连接数据库的时候,从这个“池子”中取出一个连接对象使用,使用完毕后,不会将这个连接对象关闭,而是将这个连接对象放回“池子”中,实现复用,节省资源。
19.2 Druid连接池使用步骤
19.2.1 引入相关jar包
在lib文件夹中引入druid-1.1.5.jar文件和mysql-connector-java-5.1.0-bin.jar文件,并将两个jar文件配置到项目中。
19.2.2 创建database.properties配置文件
在src文件夹下创建database.properties配置文件,配置文件中内容如下:
# 连接设置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdatabase
username=root
password=123456
# 初始化连接,连接池连接对象数量
initialSize=10
#最大连接数
maxActive=30
#最小空闲连接
maxIdle=5
#超时等待时间(毫秒为单位)
maxWait=3000
19.2.3 编写连接池工具类
package com.cxyzxc.www.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DBUtils {
// 声明一个连接池对象
private static DruidDataSource druidDataSource;
static {
// 实例化配置文件对象
Properties properties = new Properties();
try {
// 加载配置文件内容
InputStream is = DBUtils.class
.getResourceAsStream("/database.properties");
properties.load(is);
// 创建连接池
druidDataSource = (DruidDataSource) DruidDataSourceFactory
.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection() {
try {
// 通过连接池获得连接对象
return druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 释放资源,将连接对象放入连接池中
public static void closeAll(Connection connection, Statement statement,
ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
// 使用完连接对象后,将连接对象还给连接池,这里的close()方法是DruidPooledConnection实现类里的close()方法,将connection连接对象还给连接池
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
19.3 Druid连接池测试
package com.cxyzxc.www.utils;
import java.sql.Connection;
public class Test {
public static void main(String[] args) {
// 获取20个连接对象,输出连接对象,地址值不同
for (int i = 1; i <= 20; i++) {
Connection connection = DBUtils.getConnection();
System.out.println(connection);
// 调用关闭连接对象的方法后,发现获取的20个连接对象地址值是同一个,说明每次从连接池中取出的连接对象是同一个
// DBUtils.closeAll(connection, null, null);
}
}
}
二十、Apache的DBUtils使用
前面的DaoUtils工具类是我们经过千难万阻自己封装的,也有一些组织给我们封装DBUtils工具类,比如Apache组织提供了一个对JDBC进行简单封装的开源工具类库Commons DbUtils类,使用它能够简化JDBC应用程序的开发,同时也不影响程序的性能。
20.1 Apache DBUtils介绍
20.1.1 Apache DBUtils特征
Apache DBUtils是java编程中的数据库操作实用工具,小巧简单实用,主要特征有:
1)对于数据表的读操作,他可以把结果转换成List,Array,Set等java集合,便于程序员操作;
2)对于数据表的写操作,也变得很简单(只需写sql语句)
3)可以使用数据源,使用JNDI,数据库连接池等技术来优化性能–重用已经构建好的数据库连接对象,而不像php,asp那样,费时费力的不断重复的构建和析构这样的对象。
20.1.2 Apache DbUtils主要组成
1)ResultSetHandler接口:转换类型接口
- BeanHandler类:实现类,把一条记录转换成对象。
- BeanListHandler类:实现类,把多条记录转换成List集合。
- ScalarHandler类:实现类,适合获取一行一列的数据。
2)QueryRunner类:执行SQL语句的类
- update()方法:增、删、改
- query()方法:查询
20.1.3 Apache DbUtils使用步骤
1)创建lib文件夹,导入需要的jar包,并将其配置到项目中
- mysql-connector-java-5.1.0-bin.jar
- druid-1.1.5.jar
- commons-dbutils-1.7.jar
2)在src文件夹下面创建database.properties配置文件
# 连接设置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdatabase
username=root
password=123456
# 初始化连接,连接池连接对象数量
initialSize=10
#最大连接数
maxActive=30
#最小空闲连接
maxIdle=5
#超时等待时间(毫秒为单位)
maxWait=3000
3)编写DBUtils连接池工具类
package com.cxyzxc.www.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DBUtils {
// 声明一个连接池对象
private static DruidDataSource druidDataSource;
static {
// 实例化配置文件对象
Properties properties = new Properties();
try {
// 加载配置文件内容
InputStream is = DBUtils.class
.getResourceAsStream("/database.properties");
properties.load(is);
// 创建连接池
druidDataSource = (DruidDataSource) DruidDataSourceFactory
.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//返回一个数据源
public static DataSource getDataSource(){
return druidDataSource;
}
}
20.2 综合案例
20.2.1 创建product表
CREATE TABLE IF NOT EXISTS `product` (
`pid` INT PRIMARY KEY AUTO_INCREMENT COMMENT '产品编号',
`pname` VARCHAR(20) NOT NULL COMMENT '产品名称',
`price` DOUBLE NOT NULL COMMENT '产品价格',
`birthday` DATE NOT NULL COMMENT '产品生产日期'
);
20.2.2 向表中添加数据
INSERT INTO `product`(`pid`,`pname`,`price`,`birthday`)VALUES(1001,'虎皮凤爪',20.5,'2022-06-12');
INSERT INTO `product`(`pid`,`pname`,`price`,`birthday`)VALUES(1002,'卧龙锅巴',18.5,'2022-09-22');
20.2.3 创建实体类Product
package com.cxyzxc.www.entity;
import java.util.Date;
public class Product {
private int pid;
private String pname;
private double price;
private Date birthday;
public Product() {
super();
}
public Product(String pname, double price, Date birthday) {
super();
this.pname = pname;
this.price = price;
this.birthday = birthday;
}
public Product(int pid, String pname, double price, Date birthday) {
super();
this.pid = pid;
this.pname = pname;
this.price = price;
this.birthday = birthday;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Product [pid=" + pid + ", pname=" + pname + ", price=" + price
+ ", birthday=" + birthday + "]";
}
}
20.2.4 创建ProductDao接口
package com.cxyzxc.www.dao;
import java.util.List;
import com.cxyzxc.www.entity.Product;
public interface ProductDao {
//添加
int insert(Product product);
//删除
int delete(int pid);
//修改
int update(Product product);
//查询单个
Product selectOne(int pid);
//查询所有
List<Product> selectAll();
}
20.2.4 创建ProductDaoImpl实现类
package com.cxyzxc.www.dao.impl;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.cxyzxc.www.dao.ProductDao;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DBUtils;
import com.cxyzxc.www.utils.DateUtils;
public class ProductDaoImpl implements ProductDao {
// 创建QueryRunner对象,并传递一个数据源对象
private QueryRunner queryRunner = new QueryRunner(DBUtils.getDataSource());
@Override
public int insert(Product product) {
String sql = "INSERT INTO `product`(`pname`,`price`,`birthday`)VALUES(?,?,?);";
Object[] args = { product.getPname(), product.getPrice(),
DateUtils.utilDateToSqlDate(product.getBirthday()) };
try {
return queryRunner.update(sql, args);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int delete(int pid) {
String sql = "DELETE FROM `product` WHERE `pid` = ?;";
try {
return queryRunner.update(sql, pid);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int update(Product product) {
String sql = "UPDATE `product` SET `pname` = ?,`price`=?,`birthday`=? WHERE `pid`=?;";
Object[] args = { product.getPname(), product.getPrice(),
DateUtils.utilDateToSqlDate(product.getBirthday()),
product.getPid() };
try {
return queryRunner.update(sql, args);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Product selectOne(int pid) {
// 查询一个数据,使用BeanHandler将记录转换为对象
BeanHandler<Product> product = new BeanHandler<Product>(Product.class);
String sql = "SELECT * FROM `product` WHERE `pid`=?;";
try {
return queryRunner.query(sql, product, pid);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Product> selectAll() {
// 查询一个数据,使用BeanHandler将记录转换为对象
BeanListHandler<Product> productList = new BeanListHandler<Product>(Product.class);
String sql = "SELECT * FROM `product`;";
try {
return queryRunner.query(sql, productList);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
20.2.5 创建ProductService接口
package com.cxyzxc.service;
import java.util.List;
import com.cxyzxc.www.entity.Product;
public interface ProductService {
//增加
int addProduct(Product product);
//删除
int deleteProduct(int pid);
//修改
int updateProduct(Product product);
//查询单个
Product selectOneProduct(int pid);
//查询所有
List<Product> selectAllProduct();
}
20.2.6 创建ProductServiceImpl实现类
package com.cxyzxc.service.impl;
import java.util.List;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.www.dao.ProductDao;
import com.cxyzxc.www.dao.impl.ProductDaoImpl;
import com.cxyzxc.www.entity.Product;
public class ProductServiceImpl implements ProductService {
ProductDao productDao = new ProductDaoImpl();
@Override
public int addProduct(Product product) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(product.getPid());
if (pd == null) {
return productDao.insert(product);
} else {
System.out.println("商品已经存在,不能重复添加");
}
return 0;
}
@Override
public int deleteProduct(int pid) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(pid);
if (pd != null) {
return productDao.delete(pid);
} else {
System.out.println("商品不存在,不能删除");
}
return 0;
}
@Override
public int updateProduct(Product product) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(product.getPid());
if (pd!= null) {
return productDao.update(product);
} else {
System.out.println("商品不存在,不能修改");
}
return 0;
}
@Override
public Product selectOneProduct(int pid) {
Product product =productDao.selectOne(pid);
if(product!=null){
return product;
}else{
System.out.println("没有你要查找产品,查找失败");
}
return null;
}
@Override
public List<Product> selectAllProduct() {
List<Product> productList = productDao.selectAll();
if(productList.size()!=0){
return productList;
}else{
System.out.println("数据库为空,没有产品");
}
return null;
}
}
20.2.7 创建测试类
20.2.7.1 测试插入数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DateUtils;
public class Test01InsertProduct {
public static void main(String[] args) {
//创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
//增加产品
Product product = new Product(1003,"流心威化饼干", 13.5, DateUtils.strDateToUtilDate("2022-11-10"));
int result = productService.addProduct(product);
String str = result==1?"商品添加成功":"商品添加失败";
System.out.println(str);
}
}
20.2.7.2 测试删除数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
public class Test02DeleteProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
int result = productService.deleteProduct(1003);
String str = result == 1 ? "删除成功" : "删除失败";
System.out.println(str);
}
}
20.2.7.3 测试修改数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DateUtils;
public class Test03UpdateProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
// 增加产品
Product product = new Product(1002, "流心威化饼干", 13.5,
DateUtils.strDateToUtilDate("2022-11-10"));
int result = productService.updateProduct(product);
String str = result == 1 ? "修改成功" : "修改失败";
System.out.println(str);
}
}
20.2.7.4 测试查询一条数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
public class Test04SelectOneProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
Product product = productService.selectOneProduct(1003);
if (product != null) {
System.out.println(product);
} else {
System.out.println("你要查询的商品不存在");
}
}
}
20.2.7.5 测试查询所有数据
package com.cxyzxc.www.view;
import java.util.List;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
public class Test05SelectAllProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
List<Product> productList = productService.selectAllProduct();
for (int i = 0; i < productList.size(); i++) {
System.out.println(productList.get(i));
}
}
}
自此,JDBC所有知识点学习完毕。希望大家多看笔记多理解笔记,多写写笔记中的代码,熟练掌握所有技能。
urce(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//返回一个数据源
public static DataSource getDataSource(){
return druidDataSource;
}
}
## 20.2 综合案例
### 20.2.1 创建product表
CREATE TABLE IF NOT EXISTS product
(
pid
INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘产品编号’,
pname
VARCHAR(20) NOT NULL COMMENT ‘产品名称’,
price
DOUBLE NOT NULL COMMENT ‘产品价格’,
birthday
DATE NOT NULL COMMENT ‘产品生产日期’
);
### 20.2.2 向表中添加数据
INSERT INTO product
(pid
,pname
,price
,birthday
)VALUES(1001,‘虎皮凤爪’,20.5,‘2022-06-12’);
INSERT INTO product
(pid
,pname
,price
,birthday
)VALUES(1002,‘卧龙锅巴’,18.5,‘2022-09-22’);
### 20.2.3 创建实体类Product
package com.cxyzxc.www.entity;
import java.util.Date;
public class Product {
private int pid;
private String pname;
private double price;
private Date birthday;
public Product() {
super();
}
public Product(String pname, double price, Date birthday) {
super();
this.pname = pname;
this.price = price;
this.birthday = birthday;
}
public Product(int pid, String pname, double price, Date birthday) {
super();
this.pid = pid;
this.pname = pname;
this.price = price;
this.birthday = birthday;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Product [pid=" + pid + ", pname=" + pname + ", price=" + price
+ ", birthday=" + birthday + "]";
}
}
### 20.2.4 创建ProductDao接口
package com.cxyzxc.www.dao;
import java.util.List;
import com.cxyzxc.www.entity.Product;
public interface ProductDao {
//添加
int insert(Product product);
//删除
int delete(int pid);
//修改
int update(Product product);
//查询单个
Product selectOne(int pid);
//查询所有
List<Product> selectAll();
}
### 20.2.4 创建ProductDaoImpl实现类
package com.cxyzxc.www.dao.impl;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.cxyzxc.www.dao.ProductDao;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DBUtils;
import com.cxyzxc.www.utils.DateUtils;
public class ProductDaoImpl implements ProductDao {
// 创建QueryRunner对象,并传递一个数据源对象
private QueryRunner queryRunner = new QueryRunner(DBUtils.getDataSource());
@Override
public int insert(Product product) {
String sql = "INSERT INTO `product`(`pname`,`price`,`birthday`)VALUES(?,?,?);";
Object[] args = { product.getPname(), product.getPrice(),
DateUtils.utilDateToSqlDate(product.getBirthday()) };
try {
return queryRunner.update(sql, args);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int delete(int pid) {
String sql = "DELETE FROM `product` WHERE `pid` = ?;";
try {
return queryRunner.update(sql, pid);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int update(Product product) {
String sql = "UPDATE `product` SET `pname` = ?,`price`=?,`birthday`=? WHERE `pid`=?;";
Object[] args = { product.getPname(), product.getPrice(),
DateUtils.utilDateToSqlDate(product.getBirthday()),
product.getPid() };
try {
return queryRunner.update(sql, args);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Product selectOne(int pid) {
// 查询一个数据,使用BeanHandler将记录转换为对象
BeanHandler<Product> product = new BeanHandler<Product>(Product.class);
String sql = "SELECT * FROM `product` WHERE `pid`=?;";
try {
return queryRunner.query(sql, product, pid);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Product> selectAll() {
// 查询一个数据,使用BeanHandler将记录转换为对象
BeanListHandler<Product> productList = new BeanListHandler<Product>(Product.class);
String sql = "SELECT * FROM `product`;";
try {
return queryRunner.query(sql, productList);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
### 20.2.5 创建ProductService接口
package com.cxyzxc.service;
import java.util.List;
import com.cxyzxc.www.entity.Product;
public interface ProductService {
//增加
int addProduct(Product product);
//删除
int deleteProduct(int pid);
//修改
int updateProduct(Product product);
//查询单个
Product selectOneProduct(int pid);
//查询所有
List<Product> selectAllProduct();
}
### 20.2.6 创建ProductServiceImpl实现类
package com.cxyzxc.service.impl;
import java.util.List;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.www.dao.ProductDao;
import com.cxyzxc.www.dao.impl.ProductDaoImpl;
import com.cxyzxc.www.entity.Product;
public class ProductServiceImpl implements ProductService {
ProductDao productDao = new ProductDaoImpl();
@Override
public int addProduct(Product product) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(product.getPid());
if (pd == null) {
return productDao.insert(product);
} else {
System.out.println("商品已经存在,不能重复添加");
}
return 0;
}
@Override
public int deleteProduct(int pid) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(pid);
if (pd != null) {
return productDao.delete(pid);
} else {
System.out.println("商品不存在,不能删除");
}
return 0;
}
@Override
public int updateProduct(Product product) {
// 查询添加的商品是否存在
Product pd = productDao.selectOne(product.getPid());
if (pd!= null) {
return productDao.update(product);
} else {
System.out.println("商品不存在,不能修改");
}
return 0;
}
@Override
public Product selectOneProduct(int pid) {
Product product =productDao.selectOne(pid);
if(product!=null){
return product;
}else{
System.out.println("没有你要查找产品,查找失败");
}
return null;
}
@Override
public List<Product> selectAllProduct() {
List<Product> productList = productDao.selectAll();
if(productList.size()!=0){
return productList;
}else{
System.out.println("数据库为空,没有产品");
}
return null;
}
}
### 20.2.7 创建测试类
#### 20.2.7.1 测试插入数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DateUtils;
public class Test01InsertProduct {
public static void main(String[] args) {
//创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
//增加产品
Product product = new Product(1003,"流心威化饼干", 13.5, DateUtils.strDateToUtilDate("2022-11-10"));
int result = productService.addProduct(product);
String str = result==1?"商品添加成功":"商品添加失败";
System.out.println(str);
}
}
#### 20.2.7.2 测试删除数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
public class Test02DeleteProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
int result = productService.deleteProduct(1003);
String str = result == 1 ? "删除成功" : "删除失败";
System.out.println(str);
}
}
#### 20.2.7.3 测试修改数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
import com.cxyzxc.www.utils.DateUtils;
public class Test03UpdateProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
// 增加产品
Product product = new Product(1002, "流心威化饼干", 13.5,
DateUtils.strDateToUtilDate("2022-11-10"));
int result = productService.updateProduct(product);
String str = result == 1 ? "修改成功" : "修改失败";
System.out.println(str);
}
}
#### 20.2.7.4 测试查询一条数据
package com.cxyzxc.www.view;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
public class Test04SelectOneProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
Product product = productService.selectOneProduct(1003);
if (product != null) {
System.out.println(product);
} else {
System.out.println("你要查询的商品不存在");
}
}
}
#### 20.2.7.5 测试查询所有数据
package com.cxyzxc.www.view;
import java.util.List;
import com.cxyzxc.service.ProductService;
import com.cxyzxc.service.impl.ProductServiceImpl;
import com.cxyzxc.www.entity.Product;
public class Test05SelectAllProduct {
public static void main(String[] args) {
// 创建ProductService引用,指向ProductServiceImpl实现类
ProductService productService = new ProductServiceImpl();
List<Product> productList = productService.selectAllProduct();
for (int i = 0; i < productList.size(); i++) {
System.out.println(productList.get(i));
}
}
}
**自此,JDBC所有知识点学习完毕。希望大家多看笔记多理解笔记,多写写笔记中的代码,熟练掌握所有技能。**