JDBC学习笔记

一、数据库连接回顾

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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的所有数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的所有数据
 * 
 * @author 程序员张小厨
 * 
 */
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
 * 
 * @author 程序员张小厨
 * 
 */
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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的所有数据
 * 
 * @author 程序员张小厨
 * 
 */
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类
 * 
 * @author 程序员张小厨
 * 
 */
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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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类
 * 
 * @author 程序员张小厨
 *
 */
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注入

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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注入问题
 * 
 * @author 程序员张小厨
 *
 */

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 创建表

创建一张用户表people,表的字段如下:

​ 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语言常规应用层面的日期时间类型,可以通过字符串创建对应的日期时间对象,但是已经过时。常用构造方法如下(很多构造方法已经过时):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(2)不能直接通过JDBC将java.util.Date类型数据插入到数据库中。

10.3.2 java.sql.Date

(1)不可以通过字符串创建对应的时间对象,只能通过毫秒值创建对象(1970年1月1日0点0分0秒至今的毫秒值),常用构造方法如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(2)可以直接通过JDBC将java.sql.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类应用
 * 
 * @author 程序员张小厨
 * 
 */
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
 * 
 * @author 程序员张小厨
 * 
 */
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类
 * 
 * @author 程序员张小厨
 * 
 */
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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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.*;

/**
 * 重用性方案 注册驱动 获取连接 释放资源
 * 
 * @author 程序员张小厨
 *
 */
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;

/**
 * 跨平台方案 注册驱动 获取连接 释放资源
 * 
 * @author 程序员张小厨
 * 
 */
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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中插入一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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表中的一条数据
 * 
 * @author 程序员张小厨
 * 
 */
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','1319866976@qq.com','安徽合肥蜀山区长江西路132号');

INSERT INTO `teacher` VALUES(1002,'lisi',31,'1991-9-16','147589641@qq.com','安徽合肥新站区环城西路12号');

12.2 封装实体类Teacher

创建entity实体类Teacher类,封装属性,添加无参构造方法和有参构造方法,添加getXxx()/setXxx()方法

package com.cxyzxc.www.examples03;

/**
 * entity实体类Teacher类
 * 
 * @author 程序员张小厨
 */
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;

/**
 * 
 * @author 程序员张小厨
 * 
 */
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), "1319866123@qq.com","安徽合肥蜀山区淠河路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), "1319869999@qq.com","安徽合肥蜀山区淠河路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)业务逻辑:

  1. 首先在数据库中查询你要注册的账号是否存在(根据身份证号码查询,身份证号码具有唯一性)
  2. 如果查询不到你想要注册的账号,则将你注册的账号存入employee表中
  3. 如果查询到了你要注册的账号名称,则提示账号已存在,不能注册

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','1319866912@qq.com','安徽合肥蜀山区');

INSERT INTO `employee` VALUES(1002,'lisi',25,'男','1997-12-26','340825199712261396','13845682233','1396548732@qq.com','安徽合肥瑶海区');
3、封装实体类Employee
package com.cxyzxc.www.examples04;

import java.util.Date;
/**
 * entity实体类Employee
 * 
 * @author 程序员张小厨
 *
 */
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", "13877884455@qq.com","安徽合肥肥西");

		employeeServiceImpl.register(employee);

	}

}

13.3 Service开发流程(转账业务)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

13.3.1 业务需求和逻辑

(1)业务需求:

  • 一个账户向另一个账户转账

(2)业务逻辑:

  1. 首先在数据库中查询转账账号是否存在
  2. 然后在数据库中查询转账账号密码是否存在
  3. 再验证转账账号的余额是否足够转账
  4. 再验证收款账号是否存在
  5. 执行转账操作,转账账号余额减少,收款账号余额增加(减少的金额与增加的金额相等)

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类
 * 
 * @author 程序员张小厨
 *
 */
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;

/**
 * 跨平台方案 注册驱动 获取连接 释放资源
 * 
 * @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();
		}
	}
}

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;

/**
 * 跨平台方案 注册驱动 获取连接 释放资源
 * 
 * @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);
		}
	}
}

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类
 * 
 * @author 程序员张小厨
 * 
 */
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表增删改查的方法
 * 
 * @author 程序员张小厨
 *
 */
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接口,重写接口中的增删改查方法
 * 
 * @author 程序员张小厨
 *
 */
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接口,接口中定义业务逻辑方法
 * 
 * @author 程序员张小厨
 *
 */
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接口中的所有方法
 * 
 * @author 程序员张小厨
 *
 */
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
 * 
 * @author 程序员张小厨
 * 
 */
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
 * 
 * @author 程序员张小厨
 *
 */
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;
import com.cxyzxc.www.utils.DaoUtils;

/**
 * 
 * @author 程序员张小厨
 * 
 */
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"), "13645678912@qq.com", "安徽合肥庐阳区");
		
		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"),
				"13677881122@qq.com", "安徽合肥政务区");

		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
 * 
 * @author 程序员张小厨
 * @param <T>
 *
 */
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
 * 
 * @author 程序员张小厨
 * @param <T>
 *
 */
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;

/**
 * 
 * @author 程序员张小厨
 * 
 */
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所有知识点学习完毕。希望大家多看笔记多理解笔记,多写写笔记中的代码,熟练掌握所有技能。**

相关推荐

  1. JDBC学习笔记第十一篇

    2024-04-05 02:38:02       42 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-05 02:38:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-05 02:38:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-05 02:38:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-05 02:38:02       20 阅读

热门阅读

  1. 元宇宙虚拟空间的加载管理(三)

    2024-04-05 02:38:02       16 阅读
  2. 字符串处理算法

    2024-04-05 02:38:02       14 阅读
  3. 零日攻击

    2024-04-05 02:38:02       15 阅读
  4. 01背包问题

    2024-04-05 02:38:02       15 阅读
  5. 从Jenkinsfile构建到k8s部署

    2024-04-05 02:38:02       17 阅读
  6. Git/GitHub/Gitee⼯作流最佳实践

    2024-04-05 02:38:02       15 阅读
  7. 机器学习——典型的卷积神经网络

    2024-04-05 02:38:02       14 阅读
  8. 第十三题:天干地支

    2024-04-05 02:38:02       16 阅读
  9. 什么叫地下水年龄?

    2024-04-05 02:38:02       12 阅读