目录
1 PreparedStatement 和 Statement 区别
2 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况
3 使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象
4 将多条记录封装成集合 List,集合中每个元素是一个 JavaBean 实体类
一 传统的JDBC编程,操作数据库的方式
1 JDBC介绍
JDBC是Java访问数据库的标准规范,真正操作数据库还需要具体的实现类,也就是数据库驱动。
使用 JDBC 的好处:
- 程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。
- 使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库。
![](https://img-blog.csdnimg.cn/20210827111947879.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA56CB5bCP6Iqx,size_20,color_FFFFFF,t_70,g_se,x_16)
2 JDBC开发说明
使用JDBC开发使用到的包
JDBC核心的API
导入驱动jar包
在开始使用前需要先导入驱动jar包,mysql-connector-java-5.1.37-bin.jar,并添加到库
需要加载和注册驱动
3 DriverManager类
作用是管理和注册驱动,创建数据库的连接
类中的方法
使用JDBC连接数据库的四个参数
连接数据库的URL地址格式
乱码的处理
如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
4 Connection接口
作用,代表一个连接对象
5 Statement接口
作用:代表一条语句对象,用于发送SQL语句给服务器,执行静态SQL语句并返回生成结果对象。
方法
释放资源
- 需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接
- 释放原则:先开的后关,后开的先关。ResultSet->Statement->Connection
- 放在哪个代码块中:finally 块
6 ResultSet接口
作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。
方法
常用数据类型转换表
其中 java.sql.Date、Time、Timestamp(时间戳),三个共同父类是:java.util.Date
7 JDBC访问数据库的步骤
- 注册和加载驱动(可以省略)
- 获取连接 Connection
- 获取 Statement 对象
- 使用 Statement 对象执行 SQL 语句
- 返回结果集
- 释放资源
8 编程实例
需求:使用JDBC在MySQL中创建一张学生表,执行的DDL操作
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCTest {
public static void main(String[] args) {
/**
* 执行DDL操作,在MySQL数据库的test中创建一张学生表
* id int primary key auto_increment,
* name varchar(20) not null,
* gender boolean,
* birthday date
*/
Connection conn = null;
Statement statement = null;
try {
//1.创建连接
conn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
//2.通过连接对象得到语句对象
statement = conn.createStatement();
//3.通过语句对象发送SQL语句给服务器,并且执行SQL
statement.executeUpdate("create table student(id int PRIMARY KEY auto_increment,"+
"name VARCHAR (20) not null,gender boolean,birthday date)");
//4.返回影响行数(DDL没有返回值)
System.out.println("创建表成功");
} catch (SQLException e) {
e.printStackTrace();
}finally {
//5.释放资源,关闭之前要先判断
if(statement != null){
try{
statement.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(conn != null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
}
需求:执行DML操作,向学生表中添加 4 条记录,主键是自动增长
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class DMLTest {
public static void main(String[] args) throws SQLException {
/**
* 向学生表中添加4条记录,主键是自增长
* 步骤:
* 1. 创建连接对象
* 2. 创建Statement语句对象
* 3. 执行SQL语句 executeUpdate(sql)
* 4. 返回影响的行数
* 5.释放资源
*/
//创建连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql:///test","root","root");
//创建Statement语句对象
Statement statement = connection.createStatement();
//执行SQL语句并返回影响的行数
int count = 0;
count += statement.executeUpdate("insert into student values(null,'孙悟空',1,'1993-03-24')");
count += statement.executeUpdate("insert into student values(null,'白骨精',0,'1995-06-13')");
count += statement.executeUpdate("insert into student values(null,'猪八戒',1,'1903-03-24')");
count += statement.executeUpdate("insert into student values(null,'嫦娥',0,'1993-03-11')");
System.out.println("插入了" + count + "条记录");
//释放资源
statement.close();
connection.close();
}
}
查看数据库,发现执行插入语句成功
需求:确保数据库中有 3 条以上的记录,查询所有的学员信息
import java.sql.*;
public class DQLTest {
public static void main(String[] args) throws SQLException {
/**
* 需求 确保数据库中有 3 条以上的记录,查询所有的学员信息
* 步骤
* 1.得到连接对象
* 2.得到语句对象
* 3.执行 SQL 语句得到结果集 ResultSet 对象
* 4.循环遍历取出每一条记录
* 5.输出的控制台上
* 6.释放资源
*/
//1.创建连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql:///test","root","root");
//2.创建Statement语句对象
Statement statement = connection.createStatement();
//3.执行SQL语句得到结果集ResultSet对象
ResultSet resultSet = statement.executeQuery("select * from student");
//4.循环遍历取出每一条记录
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
boolean gender = resultSet.getBoolean("gender");
Date birthday = resultSet.getDate("birthday");
//5.输出到控制台
System.out.println("编号:"+id+",姓名:"+name+",性别:"+gender+",生日:"+birthday);
}
//6.释放资源
resultSet.close();
statement.close();
connection.close();
}
}
控制台打印输出的结果
关于 ResultSet 接口中的注意事项:
- 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set
- 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set
- 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection
二 数据库工具类 JdbcUtils
如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。
1 工具类的创建
创建类JdbcUtils包含3个方法
- 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
- 得到数据库的连接:getConnection()
- 关闭所有打开的资源 close(Connection conn, Statement stmt),close(Connection conn, Statement stmt, ResultSet rs)
import java.sql.*;
/**
* 访问数据的工具类
*/
public class JdbcUtils {
//把几个字符串定义为常量:用户名,密码,URL,驱动类
private static final String USER = "root";
private static final String PWD = "root";
private static final String URL = "jdbc:mysql://localhost:3306/test";
private static final String DRIVER = "com.mysql.jdbc.Driver";
/**
* 注册驱动
*/
static {
try{
Class.forName(DRIVER);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
/**
* 得到数据库的连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(URL,USER,PWD);
}
/**
* 关闭所有打开的资源
* @param conn
* @param statement
*/
public static void close(Connection conn, Statement statement){
if(statement != null){
try{
statement.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(conn != null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
/**
* 关闭所有打开的资源
* @param connection
* @param statement
* @param resultSet
*/
public static void close(Connection connection, Statement statement, ResultSet resultSet){
if(resultSet != null){
try{
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
}
close(connection,statement);
}
}
2 用户登录案例说明JdbcUtils的使用方法
需要有一张用户表和几条用户的记录
#创建用户表
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
PASSWORD VARCHAR(20)
);#在表中添加记录
INSERT INTO USER VALUES(NULL,'jack','123'),(NULL,'rose','456');
#登录,SQL中大小写不敏感
SELECT * FROM USER WHERE NAME='JACK' AND PASSWORD='123';
#登陆失败
SELECT * FROM USER WHERE NAME='JACK' AND PASSWORD='333';
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class LoginTest {
/**
* 步骤:
* 1.得到用户从控制台上输入的用户名和密码来查询数据库
* 2.写一个登录的方法,包括:
* a.通过工具类得到连接
* b.创建语句对象,使用拼接字符串的方式生成 SQL 语句
* c.查询数据库,如果有记录则表示登录成功,否则登录失败
* d.释放资源
* @param args
*/
public static void main(String[] args) {
//从控制台上输入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
login(name,password);
}
/**
* 登录方法
* @param name
* @param password
*/
public static void login(String name,String password){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try{
//通过工具类得到连接
connection = JdbcUtils.getConnection();
//创建语句对象
statement = connection.createStatement();
//使用拼接字符串的方式生成SQL语句
String sql = "select * from user where name='"+name+"' and password='"+password+"'";
System.out.println(sql);
//查询数据库,如果有记录,则表示登录成功,否则登陆失败
resultSet = statement.executeQuery(sql);
if(resultSet.next()){
System.out.println("登录成功,欢迎您:" + name);
}else{
System.out.println("登陆失败");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.close(connection,statement,resultSet);
}
}
}
3 SQL注入问题
对于上面的sql语句查询的方式,使用字符串拼接参数,当输入下面的密码后,也可以成功登录。因此, 我们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容作为了 SQL 语句语法的一部分,改变了 原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进行简单的字符串拼接。
三 PreparedStatement接口
1 PreparedStatement 和 Statement 区别
PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的SQL 语句,和Statement对象的区别是:
- Statement对象每执行一条SQL语句都会先将SQL语句发送给数据库,数据库先编译SQL,再执行。如果有1万条类似的SQL语句,数据库要编译1万次,执行1万次,效率低。
- PreparedStatement会将SQL语句发送给数据库预编译,PreparedStatement会引用编译后的结果。可以多次传入不同的参数给PreparedStatement对象并执行。如果有1万条类似的插入语句,数据库只需要编译一次,传入1万次不同的参数并执行,减少了SQL语句的编译次数,提高了执行效率。
作用
- 因为有预先编译的功能,提高 SQL 的执行效率。
- 可以有效的防止 SQL 注入的问题,安全性更高
![](https://img-blog.csdnimg.cn/20210827141418342.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA56CB5bCP6Iqx,size_20,color_FFFFFF,t_70,g_se,x_16)
PreparedStatement 接口中的方法:
PreparedStatement 中设置参数的方法:
2 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况
import java.sql.*;
import java.util.Scanner;
public class LoginTest {
/**
* 使用PreparedStatement改写登录程序,解决SQL注入的问题
* 步骤:
* 1.编写SQL语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?";
* 2.获得 PreparedStatement 对象
* 3.设置实际参数:setXxx(占位符的位置, 真实的值)
* 4.执行参数化 SQL 语句
* 5.关闭资源
* @param args
*/
public static void main(String[] args) {
//从控制台上输入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
login(name,password);
}
/**
* 登录方法
* @param name
* @param password
*/
public static void login(String name,String password){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try{
//通过工具类得到连接
connection = JdbcUtils.getConnection();
//写成登录的SQL语句,没有单引号,采用占位符的方式(未知内容用?占位)
String sql = "select * from user where name=? and password=? ";
//得到语句对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//设置参数
preparedStatement.setString(1,name);
preparedStatement.setString(2,password);
//查询数据库,如果有记录,则表示登录成功,否则登陆失败
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("登录成功,欢迎您:" + name);
}else{
System.out.println("登陆失败");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
//释放资源
JdbcUtils.close(connection,statement,resultSet);
}
}
}
3 使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcStudent {
public static void main(String[] args) throws SQLException {
//创建学生对象
Student student = new Student();
Connection connection = JdbcUtils.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select * from student where id=? ");
//设置参数
preparedStatement.setInt(1,2);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
//封装成一个学生对象
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setGender(resultSet.getBoolean("gender"));
student.setBirthday(resultSet.getDate("birthday"));
}
//释放资源
JdbcUtils.close(connection,preparedStatement,resultSet);
//打印数据
System.out.println(student.toString());
}
}
4 将多条记录封装成集合 List<Student>,集合中每个元素是一个 JavaBean 实体类
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 StudentList {
public static void main(String[] args) throws SQLException {
//创建一个集合
List<Student> students = new ArrayList<>();
Connection connection = JdbcUtils.getConnection();
String sql = "select * from student";
PreparedStatement ps = connection.prepareStatement(sql);
//没有参数替换
ResultSet resultSet = ps.executeQuery();
while(resultSet.next()){
//每次循环是一个学生对象
Student student = new Student();
//封装成一个学生对象
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setGender(resultSet.getBoolean("gender"));
student.setBirthday(resultSet.getDate("birthday"));
//把数据放到集合中
students.add(student);
}
//关闭连接
JdbcUtils.close(connection,ps,resultSet);
//打印数据
for(Student stu:students){
System.out.println(stu.toString());
}
}
}
5 PreparedStatement 执行 DML 操作
package com.itcast.jdbc;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DMLPSTest {
public static void main(String[] args) throws SQLException {
// insert();
// update();
delete();
}
//插入记录
private static void insert() throws SQLException {
Connection connection = JdbcUtils.getConnection();
String sql = "insert into student values(null,?,?,?)";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1,"小白龙");
ps.setBoolean(2,true);
ps.setDate(3, Date.valueOf("1999-11-11"));
int row = ps.executeUpdate();
System.out.println("插入了" + row +"条记录");
JdbcUtils.close(connection,ps);
}
//更新记录:换名字和生日
private static void update() throws SQLException {
Connection connection = JdbcUtils.getConnection();
String sql = "update student set name=?,birthday=? where id=?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1,"黑熊怪");
ps.setDate(2, Date.valueOf("1999-03-23"));
ps.setInt(3,5);
int row = ps.executeUpdate();
System.out.println("更新了" + row +"条记录");
JdbcUtils.close(connection,ps);
}
//删除记录,删除第5条记录
private static void delete() throws SQLException {
Connection connection = JdbcUtils.getConnection();
String sql = "delete from student where id=?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1,5);
int row = ps.executeUpdate();
System.out.println("删除了" + row +"条记录");
JdbcUtils.close(connection,ps);
}
}
四 JDBC中事务的处理
1 Connection接口中关于事务的方法
2 以转账事务为例说明用法
#创建表CREATE TABLE account (id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(10),balance DOUBLE);-- 添加数据INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Transaction {
/**
* 以转账业务为例说明JDBC中事务的用法
* 主要是Connection接口中有关于事务的方法
* 步骤
* 1.获取链接
* 2.开启事务
* 3.获取到PreparedStatement
* 4.使用PreparedStatement执行两次更新操作
* 5.正常情况下提交事务
* 6.出现异常回滚事务
* 7.最后释放资源
*/
public static void main(String[] args) {
Connection connection = null;
PreparedStatement ps = null;
try{
//注册驱动,获取连接
connection = JdbcUtils.getConnection();
//开启事务
connection.setAutoCommit(false);
//获取到PreparedStatement,从Jack账户扣钱
String sql1 = "update account set balance=balance-? where name=?";
ps = connection.prepareStatement(sql1);
ps.setInt(1,500);
ps.setString(2,"Jack");
ps.executeUpdate();
//出现异常
System.out.println(100/0);
//给rose账户加钱
String sql2 = "update account set balance=balance+? where name=?";
ps = connection.prepareStatement(sql2);
ps.setInt(1,500);
ps.setString(2,"Rose");
ps.executeUpdate();
//提交事务
connection.commit();
System.out.println("转账成功");
}catch (Exception e){
e.printStackTrace();
try{
//事务的回滚
connection.rollback();
}catch (SQLException e1){
e1.printStackTrace();
}
System.out.println("转账失败");
}finally {
//释放资源
JdbcUtils.close(connection,ps);
}
}
}
五 数据库连接池
1 介绍:
数据库连接池其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。
好处:
节约资源,用户访问高效
实现
一般我们不去实现它,有数据库厂商来实现
- C3P0:数据库连接池技术
- Druid:数据库连接池实现技术,由阿里巴巴提供的
2 C3P0:数据库连接池技术
步骤:
1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,
* 不要忘记导入数据库驱动jar包
2. 定义配置文件:
* 名称: c3p0.properties 或者 c3p0-config.xml
* 路径:直接将文件放在src目录下即可。
3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
4. 获取连接: getConnection
//1.创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
//2. 获取连接对象
Connection conn = ds.getConnection();
3 Druid:数据库连接池实现技术
步骤:
1. 导入jar包 druid-1.0.9.jar
2. 定义配置文件:
* 是properties形式的
* 可以叫任意名称,可以放在任意目录下
3. 加载配置文件。Properties
4. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
5. 获取连接:getConnection
//3.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4.获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5.获取连接
Connection conn = ds.getConnection();
4 定义一个工具类,方便调用
1. 定义一个类 JDBCUtils
2. 提供静态代码块加载配置文件,初始化连接池对象
3. 提供方法
1. 获取连接方法:通过数据库连接池获取连接
2. 释放资源
3. 获取连接池的方法
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
//定义成员变量DataSource
private static DataSource ds;
static {
try{
//加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
* @param statement
* @param connection
*/
public static void close(Statement statement,Connection connection){
if(statement != null){
try{
statement.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(connection != null){
try{
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
close(null,statement,connection);
}
/**
* 释放资源
* @param resultSet
* @param statement
* @param connection
*/
public static void close(ResultSet resultSet,Statement statement, Connection connection){
if(resultSet != null){
try{
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(statement != null){
try{
statement.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(connection != null){
try{
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
close(null,statement,connection);
}
/**
* 获取连接池的方法
* @return
*/
public static DataSource getDataSource(){
return ds;
}
}
5 Spring JDBC
Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
步骤:
1. 导入jar包
2. 创建JdbcTemplate对象。依赖于数据源DataSource
* JdbcTemplate template = new JdbcTemplate(ds);
3. 调用JdbcTemplate的方法来完成CRUD的操作
- update():执行DML语句。增、删、改语句
- queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合。注意:这个方法查询的结果集长度只能是1
- queryForList():查询结果将结果集封装为list集合。 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
- query():查询结果,将结果封装为JavaBean对象。query的参数:RowMapper。一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装。new BeanPropertyRowMapper<类型>(类型.class)
- queryForObject:查询结果,将结果封装为对象。 一般用于聚合函数的查询
以案例形式说明如何使用
假设数据库中存在一张emp表,其字段如下图
我们需要创建一个Emp的实体类,用于封装从数据库中取出来的数据
其中需要注意的是,在定义字段使要使用包装类,例如Integer和Double,否则当字段为空的时候会报错
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class JdbcTemplateTest {
/**
* 使用Spring JDBC中的JDBCTemplate对象简化JDBC的开发
* 需求
* 1. 修改1号数据的 salary 为 10000
* 2. 添加一条记录
* 3. 删除刚才添加的记录
* 4. 查询id为1的记录,将其封装为Map集合
* 5. 查询所有记录,将其封装为List
* 6. 查询所有记录,将其封装为Emp对象的List集合
* 7. 查询总记录数
*/
//Junit单元测试,可以让方法独立执行
//1.获取JDBCTemplate对象
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 1. 修改1号数据的 salary 为 10000
*/
@Test
public void test1(){
String sql = "update emp set salary=1000 where id=1001";
int count = template.update(sql);
System.out.println(count);
}
/**
* 2. 添加一条记录
*/
@Test
public void test2(){
String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
int count = template.update(sql,1006,"郭靖",10);
System.out.println(count);
}
/**
* 3.删除刚才添加的记录
*/
@Test
public void test3(){
String sql = "delete from emp where id=?";
int count = template.update(sql,1006);
System.out.println(count);
}
/**
* 4.查询id为1001的记录,将其封装为Map集合
* 注意:这个方法查询的结果集长度只能是1
*/
@Test
public void test4(){
String sql = "select * from emp where id = ?";
Map<String, Object> map = template.queryForMap(sql, 1001);
System.out.println(map);
}
/**
* 5. 查询所有记录,将其封装为List
*/
@Test
public void test5(){
String sql = "select * from emp";
List<Map<String, Object>> list = template.queryForList(sql);
for(Map<String, Object> stringObjectMap:list){
System.out.println(stringObjectMap);
}
}
/**
* 6. 查询所有记录,将其封装为Emp对象的List集合
*/
@Test
public void test6(){
String sql = "select * from emp";
List<Emp> list = template.query(sql, new RowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet resultSet, int i) throws SQLException {
Emp emp = new Emp();
int id = resultSet.getInt("id");
String ename = resultSet.getString("ename");
int job_id = resultSet.getInt("job_id");
int mgr = resultSet.getInt("mgr");
Date joindate = resultSet.getDate("joindate");
double salary = resultSet.getDouble("salary");
double bonus = resultSet.getDouble("bonus");
int dept_id = resultSet.getInt("dept_id");
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setMgr(mgr);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
return emp;
}
});
for(Emp emp:list){
System.out.println(emp);
}
}
/**
* 7. 查询所有记录,将其封装为Emp对象的List集合
*/
@Test
public void test7(){
String sql = "select * from emp";
List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for(Emp emp:list){
System.out.println(emp);
}
}
/**
* 8. 查询总记录数
*/
@Test
public void test8(){
String sql = "select count(id) from emp";
Long total = template.queryForObject(sql, Long.class);
System.out.println(total);
}
}