各个版本有各个的依赖包,想MySQL8.0 和MySQL5.0 应该下载对应的依赖包
在idea项目当中创建文件夹libs来放相关的依赖,将依赖放进去后,右击,增加到此项目当中(如图一),加载完成之后会有三角形的这个依赖包可以打开,如图二所示:
图一:
* TODO: 步骤总结 (6步)
* 1. 注册驱动
* 2. 获取连接
* 3. 创建statement或者Prepared
* 4. 发送SQL语句,并获取结果
* 5. 结果集解析
* 6. 关闭资源
1.注册驱动
// 方法1:
DriverManager.registerDriver(new Driver());// 这个驱动会创建两次
//方法2:利用反射机制-推荐
Class.forName("com.mysql.cj.jdbc.Driver");
2.获取链接
获取链接的有三个参数的,两个参数的,一个参数的。接下来一个一个介绍
// 三个参数
public static Connection getConnection(String url,
String user, String password)
//两个参数
public static Connection getConnection(String url,
java.util.Properties info)
// 一个参数
public static Connection getConnection(String url)
三个参数的:
/**
这里有三个参数,具体在这里详细描述【】——》带这个的是你需要里面需要填的东西。
第一个参数:(String URL: 连接数据库地址) 连接数据库地址模仿下列的写法 jbdc:【数据库名】://【域名或ip地址】:【端口号】/【数据库名】
其实还可以有其他的参数:
第二个参数:(String user: 连接数据库用户名)
第三个参数:连接数据库用户对应的密码
*/
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","root");
数据库URL语法:
(1)链接Oracle数据库 ip 127.0.0.1 端口号:3306 数据库名:db
jdbc:oracle :// 127.0.0.1 : 3306 / db
(2)链接Mysql数据库 ip 本机 端口号:3306 数据库名:day01
jdbc:mysql://localhost:3306/day01
(3) 当前电脑的省略写法! 注意:本机和端口3306
jdbc:mysql://localhost:3306/day01相当于jdbc:mysql:///day01
两个参数的:
String URL : 写法还是jdbc的三个参数的写法!
Properties : 就是一个参数封装容器!至少要包含 user / password key!存储连接账号信息!(就是properties配置文件需要自己写)
一个参数的:
String URL: URl可以携带目标地址,可以通过?分割,在后面key=value&key=value形式传递参数
jdbc:mysql:///day01?user=root&password=123456
他们的区别就在于statement,只能给字符串,可以形成SQL注入,而prepared可以给一个方法传入参数,则可以防止注入。
1.statement:
Statement statement = connection.createStatement();
2.prepared
//创建preparedStatement
//TODO 需要传入SQL语句结构
//TODO 要的是SQL语句结构,动态值的部分使用 ? , 占位符!
//TODO ? 不能加 '?' ? 只能替代值,不能替代关键字和容器名
String sql = "select * from t_user where account = ? and password = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
//给占位符赋值! 从左到右,从1开始!
/**
* int 占位符的下角标
* object 占位符的值
*/
preparedStatement.setObject(2,password);
preparedStatement.setObject(1,account);
1.statement 获取
/**
这里举例:写了一个sql 语句
*/
String sql = "select id,account,password,nickname from t_user ;";
ResultSet resultSet = statement.executeQuery(sql);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet的返回值:
ResultSet 结果集对象 = executeQuery(DQL语句)
int 响应行数 = executeUpdate(非DQL语句)
5.结果集解析
/**
*
* TODO:1.需要理解ResultSet的数据结构和mysql可视化工具查询出来的是一样,需要在脑子里构建结果表!
* TODO:2.有一个光标指向的操作数据行,默认指向第一行的上边!我们需要移动光标,指向行,在获取列即可!
* boolean = next()
* false: 没有数据,也不移动了!
* true: 有更多行,并且移动到下一行!
* 推荐:推荐使用if 或者 while循环,嵌套next方法,循环和判断体内获取数据!
* if(next()){获取列的数据!} || while(next()){获取列的数据!}
*
*TODO:3.获取当前行列的数据!
* get类型(int columnIndex | String columnLabel)
* 列名获取 //lable 如果没有别名,等于列名, 有别名label就是别名,他就是查询结果的标识!
* 列的角标 //从左到右 从1开始! 数据库全是从1开始!
*/
while (resultSet.next()){
int id = resultSet.getInt("id");
String account = resultSet.getString("account");
String password = resultSet.getString("password");
String nickname = resultSet.getString("nickname");
System.out.println(id+"::"+account+"::"+password+"::"+nickname);
}
6.关闭资源
resultSet.close();
statement.close();
connection.close();
public class test {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册一次驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///my_project", "root", "Thm123456!");
//3.创建statement
Statement statement = connection.createStatement();
//4.执行SQL语句 [动态SQL语句,需要字符串拼接]
// String sql = "select * from t_user where account = '"+account+"' and password = '"+password+"' ;";
String sql = "SELECT * FROM my_work ;";
ResultSet resultSet = statement.executeQuery(sql);
// 5.使用数据
while (resultSet.next()){
System.out.println(resultSet.getString(1)); // 打印第一竖的数据
}
//关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
public class testPrepared {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册一次驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///my_project", "root", "Thm123456!");
//3.创建prepared
String sql = "SELECT * FROM my_work WHERE password = ?;"; //sql 语句
PreparedStatement preparedStatement = connection.prepareStatement(sql); // 准备prepared解析SQL语句
preparedStatement.setObject(1,"ccc"); // 第1个参数传入ccc
//4.执行SQL语句 [动态SQL语句,需要字符串拼接]
ResultSet resultSet = preparedStatement.executeQuery();
// 5.使用数据
while (resultSet.next()){
System.out.println(resultSet.getString(1)); // 打印第一竖的数据
System.out.println("name:" + resultSet.getString("name")); // 通过 名称查找 获取当前行的数据
System.out.println("password:" + resultSet.getString("password"));
}
//关闭资源
resultSet.close();
preparedStatement.close();
connection.close();
}
}
public class JdbcPreparedStatementCrudPart {
/**
* 插入一条用户数据!
* 账号: test
* 密码: test
* 昵称: 测试
*/
@Test
public void testInsert() throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///db", "root", "root");
//TODO: 切记, ? 只能代替 值!!!!! 不能代替关键字 特殊符号 容器名
String sql = "insert into t_user(account,password,nickname) values (?,?,?);";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setString(1, "test");
preparedStatement.setString(2, "test");
preparedStatement.setString(3, "测试");
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println(rows);
//关闭资源close
preparedStatement.close();
connection.close();
}
/**
* 修改一条用户数据!
* 修改账号: test的用户,将nickname改为tomcat
*/
@Test
public void testUpdate() throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///db", "root", "root");
//TODO: 切记, ? 只能代替 值!!!!! 不能代替关键字 特殊符号 容器名
String sql = "update t_user set nickname = ? where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setString(1, "tomcat");
preparedStatement.setString(2, "test");
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println(rows);
//关闭资源close
preparedStatement.close();
connection.close();
}
/**
* 删除一条用户数据!
* 根据账号: test
*/
@Test
public void testDelete() throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///db", "root", "root");
//TODO: 切记, ? 只能代替 值!!!!! 不能代替关键字 特殊符号 容器名
String sql = "delete from t_user where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setString(1, "test");
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println(rows);
//关闭资源close
preparedStatement.close();
connection.close();
}
/**
* 查询全部数据!
* 将数据存到List
@Test
public void testQueryMap() throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///db", "root", "root");
//TODO: 切记, ? 只能代替 值!!!!! 不能代替关键字 特殊符号 容器名
String sql = "select id,account,password,nickname from t_user ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值 本次没有占位符,省略
//发送查询语句
ResultSet resultSet = preparedStatement.executeQuery();
//创建一个集合
List<Map> mapList = new ArrayList<>();
//获取列信息对象
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
Map map = new HashMap();
for (int i = 1; i <= columnCount; i++) {
map.put(metaData.getColumnLabel(i), resultSet.getObject(i));
}
mapList.add(map);
}
System.out.println(mapList);
//关闭资源close
preparedStatement.close();
connection.close();
resultSet.close();
}
}
利用
try ...catch..finally
开启事务(关闭事务自动提交)
connection.setAutoCommit(false);
提交事务
connection.commit();
回滚事务
connection.rollback();
等操作,实现事务的一致性
BankDao 类(是用传入参数 用来加钱减钱的操作)
public class BankDao {
/**
* 加钱方法
* @param account
* @param money
* @param connection 业务传递的connection和减钱是同一个! 才可以在一个事务中!
* @return 影响行数
*/
public int addMoney(String account, int money,Connection connection) throws ClassNotFoundException, SQLException {
String sql = "update t_bank set money = money + ? where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println("加钱执行完毕!");
//关闭资源close
preparedStatement.close();
return rows;
}
/**
* 减钱方法
* @param account
* @param money
* @param connection 业务传递的connection和加钱是同一个! 才可以在一个事务中!
* @return 影响行数
*/
public int subMoney(String account, int money,Connection connection) throws ClassNotFoundException, SQLException {
String sql = "update t_bank set money = money - ? where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println("减钱执行完毕!");
//关闭资源close
preparedStatement.close();
return rows;
}
}
BankService类(这里注册了驱动,建立了数据库的链接,然后用了try catch 保持事务的一致性,在关闭了资源)
public class BankService {
/**
* 转账业务方法
* @param addAccount 加钱账号
* @param subAccount 减钱账号
* @param money 金额
*/
public void transfer(String addAccount,String subAccount, int money) throws ClassNotFoundException, SQLException {
System.out.println("addAccount = " + addAccount + ", subAccount = " + subAccount + ", money = " + money);
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///db", "root", "root");
int flag = 0;
//利用try代码块,调用dao
try {
//开启事务(关闭事务自动提交)
connection.setAutoCommit(false);
BankDao bankDao = new BankDao();
//调用加钱 和 减钱
bankDao.addMoney(addAccount,money,connection);
System.out.println("--------------");
bankDao.subMoney(subAccount,money,connection);
flag = 1;
//不报错,提交事务
connection.commit();
}catch (Exception e){
//报错回滚事务
connection.rollback();
throw e;
}finally {
connection.close();
}
if (flag == 1){
System.out.println("转账成功!");
}else{
System.out.println("转账失败!");
}
}
}
作用:节约了创建和销毁连接性能消耗,提升了时间效率!
总结确定:
(1)不使用数据库连接池,每次都通过DriverManager获取新连接,用完直接抛弃断开,连接的利用率太低。
(2)对于数据库服务器来说,压力太大了。我们数据库服务器和Java程序对连接数也无法控制,很容易导致数据库服务崩溃。
所以我们就希望能够管理连接:
- 我们可以建立一个连接池,这个池中可以容纳一定数量的连接对象,一开始我们就可以先替用户先创建好一些连接对象,等用户要拿连接对象时,就直接从池中拿,不用新建了,这样也可节约时间。然后用户用完之后,那么连接池可以向服务器申请新的连接放到池中。
直到池中的连接达到“最大连接数量”,就不能在申请新的连接了,如果没有拿到连接的用户只能等待。
javax.sql.DataSource 接口 :(1)规范了连接池获取的方法
(2)规范了连接池回收连接的方法
硬链接模式:
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 创建druid连接池对象,使用硬编码进行核心参数设置
* 必须要参数: 账号,密码,url,driverClass
* 非必要参数:初始化个数,最大数量等等 不推荐设置
*/
// TODO: 这里写一个硬链接模式
public class DruidTest {
public static void main(String[] args) throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
//设置四个必要的参数
druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/my_project?useUnicode=true&characterEncoding=utf-8");
druidDataSource.setUsername("root");
druidDataSource.setPassword("Thm123456!");
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
druidDataSource.setInitialSize(5); // 初始化数量
druidDataSource.setMaxActive(20); // 最大数量
//获取链接
Connection connection = druidDataSource.getConnection();
// curd
System.out.println(connection);
//回收链接
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
软连接模式:
先在项目的src下面创建一个druid.properties配置文件
文件里写入
# druid 连接池需要配置参数,key固定名字
driverClassName=com.mysql.cj.jdbc.Driver
username=root
password=Thm123456!
url=jdbc:mysql://127.0.0.1:3306/my_project
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
*这里写一个软连接的模式:
* 不直接在Java代码编写配置文件!
* 利用工厂模式,传入配置文件对象,创建连接池!
*/
public class DruidTest2 {
public static void main(String[] args) throws Exception {
//1.读取外部配置文件Properties
Properties properties = new Properties();
// 2.使用了连接池的工具类工厂模式,创建连接池
// 这里使用了类加载器 druid.properties 这个文件在src 下面
InputStream ips = DruidTest2.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(ips);
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
// 3.数据crud
// 4.回收连接
connection.close();
}
}
接下来讲一个工程来说明: example 包是之前的转钱的项目 然后用了 工具类之后然后用UtilsV2的封装的连接池工具
UtilsV1 是封装类的工具(可以用来连接和销毁,这个有一个缺陷,每次都要传connection,不推荐使用
)
UtilsV2是第二个封装的工具类(也是用来连接池,用了使用了线程本地变量存储连接信息,确保一个线程的多个方法可以获取同一个connection,就不用传connection)
BaseDao是一个封装的dao 就是操作数据库里面的数据 要使用需要继承BaseDao,里面封装了非DQL 和DQL 的两个方法(里面的连接还是用了UtilsV2)
bankDao.java
package example;
import jbdcUtils.UtilsV2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BankDao {
/**
* 加钱方法
* @param account
* @param money
* @return 影响行数
*/
public int addMoney(String account, int money) throws ClassNotFoundException, SQLException {
Connection connection = UtilsV2.getConnection();
String sql = "update t_bank set money = money + ? where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println("加钱执行完毕!");
//关闭资源close
preparedStatement.close();
return rows;
}
/**
* 减钱方法
* @param account
* @param money
* @return 影响行数
*/
public int subMoney(String account, int money) throws ClassNotFoundException, SQLException {
Connection connection = UtilsV2.getConnection();
String sql = "update t_bank set money = money - ? where account = ? ;";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//占位符赋值
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送SQL语句
int rows = preparedStatement.executeUpdate();
//输出结果
System.out.println("减钱执行完毕!");
//关闭资源close
preparedStatement.close();
return rows;
}
}
Bankservice.java
package example;
import jbdcUtils.UtilsV2;
import java.sql.Connection;
import java.sql.SQLException;
public class BankService {
/**
* 转账业务方法
* @param addAccount 加钱账号
* @param subAccount 减钱账号
* @param money 金额
*/
public void transfer(String addAccount,String subAccount, int money) throws ClassNotFoundException, SQLException {
System.out.println("addAccount = " + addAccount + ", subAccount = " + subAccount + ", money = " + money);
Connection connection = UtilsV2.getConnection();
int flag = 0;
//利用try代码块,调用dao
try {
//开启事务(关闭事务自动提交)
connection.setAutoCommit(false);
BankDao bankDao = new BankDao();
//调用加钱 和 减钱
bankDao.addMoney(addAccount,money);
System.out.println("--------------");
bankDao.subMoney(subAccount,money);
flag = 1;
//不报错,提交事务
connection.commit();
}catch (Exception e){
//报错回滚事务
connection.rollback();
throw e;
}finally {
UtilsV2.releaseConnection();
}
if (flag == 1){
System.out.println("转账成功!");
}else{
System.out.println("转账失败!");
}
}
}
UtilsV1.java
package jbdcUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* v1.0 版本工具类
* 内部包含一个连接池对象,并且对外提供获取连接和回收的方法!
*
* 小建议:工具类的方法,推荐写成静态,外部调用会更加方便!
*
* 实现:
* 属性 连接池对象 [指实例化一次] 1.单例模式, 2.用静态代码块
* static {
* 全局调用一次
* }
* 方法
* 对外提供连接方法
* 回收外部传入连接方法
*/
public class UtilsV1 {
private static DataSource dataSource = null;
static {
// 初试化连接池对象
Properties properties = new Properties();
InputStream ips = UtilsV1.class.getClassLoader().getResourceAsStream("druid.properties");
try {
properties.load(ips);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 对外提供连接方法
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 回收外部传入连接方法
*/
public static void releaseConnection(Connection connnection) throws SQLException {
connnection.close();// 连接池的连接,调用close就回收
}
}
UtlisV2.java
package jbdcUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* 之前v 1.0的工具需要每次都要传入参数比较麻烦,
* v 2.0 使用同一个线程实现的连接是同一个,就不用那么麻烦的去传参数了
*
* 这里使用了线程本地变量存储连接信息,确保一个线程的多个方法可以获取同一个connection
* 优势:在做事务操作的时候 service 和dao 方法 获取都是同一个连接池
*/
public class UtilsV2 {
private static DataSource dataSource = null;
/**
* 线程本地变量
*/
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
static {
// 初试化连接池对象
Properties properties = new Properties();
InputStream ips = UtilsV2.class.getClassLoader().getResourceAsStream("druid.properties");
try {
properties.load(ips);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 对外提供连接方法
*/
public static Connection getConnection() throws SQLException {
// 线程本地变量是否存在?
Connection connection = tl.get();
//第一次没有
if (connection == null ) {
connection = dataSource.getConnection();
tl.set(connection);
}
return connection;
}
/**
* 回收外部传入连接方法
*/
public static void releaseConnection() throws SQLException {
Connection connection = tl.get();
if (connection != null){
tl.remove(); // 清空线程本地变量
connection.setAutoCommit(true); // 事务状态回顾false,要回归到默认状态
connection.close();
}
}
}
BaseDao.java
package jbdcUtils;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* ClassName: BaseDap
* Package: jbdcUtils
* Description: 封装dao数据库重复代码!
* todo:
* 封装两个方法 一个简化非DQL
* 一个简化DQL
*
* @Author Thmiao
*/
public class BaseDao {
/**
* 封装简化DQL语句
* @param sql 带占位符的sql 语句
* @param params 占位符的值
* @return 执行影响的行数
*/
public static int executeUpdate(String sql, Object... params) throws SQLException {
Connection connection = UtilsV2.getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) { //循环赋值
ps.setObject(i + 1, params[i]);
}
int result = ps.executeUpdate();
ps.close();
// 是否回收连接,需要考虑是不是事务
if(connection.getAutoCommit()){
// 没有开启事务,正常回收
UtilsV2.releaseConnection();
}
return result;
}
/**
* 封装简化非DQL语句
* @param sql 带占位符的sql 语句
* @param clazz 要接值得实体集合的模板对象
* @param params 占位符的值
* @return list
* 数据库数据-->Java实体类
* 数据库表有 t_uer :id,account,password,nickname,
* java 层面:
* User : id ,account,password,nickname,
*
* 将查询结果封装到一个实体集合
*/
public static <T> List<T> executeQuery(String sql, Class<T> clazz, Object... params) throws Exception {
// 获取连接
Connection connection = UtilsV2.getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
if(params !=null){
for (int i = 0; i < params.length; i++) { //循环赋值
ps.setObject(i + 1, params[i]);
}
}
// 获取列信息的对象
ResultSet rs = ps.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
// 创建数组
List<T> list = new ArrayList<T>();
while (rs.next()) {
T t = clazz.newInstance(); // 调用类的无参构造函数实例化对象
// 自动遍历列,注意要从1开始,并且小于等于总列数
for (int i = 0; i <= columnCount; i++) {
// 对象的属性值
Object value = rs.getObject(i);
// 获取指定列下标的列名称!
String propertyName = metaData.getColumnLabel(i);
// 反射给对象的属性值赋值
Field field = clazz.getDeclaredField(propertyName);
// 打破private的修饰限制 属性可以设置
field.setAccessible(true);
/**
* @param t 要复制的对象 如果属性是静态的第一个参数可以为null
* @param value 要赋值的值
*/
field.set(t, value);
}
// 一行数据所有列全部存到map中
list.add(t);
}
//关闭资源
rs.close();
ps.close();
// 判断是否有事务
if(connection.getAutoCommit()){
// 没有开启事务,正常回收
UtilsV2.releaseConnection();
}
return list;
}
}
这里有一个测试CudrTest.java
package jbdcUtils;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
/**
* ClassName: CurdTest
* Package: jbdcUtils
* Description:
*
* @Author Thmiao
* @Create 2023/8/25 17:37
* @Version 1.0
*/
public class CurdTest extends BaseDao {
/**
* 这个DQl的测试
* @throws SQLException
* return 是修改的行数
*/
@Test
public void test() throws SQLException {
String sql = "DELETE * FROM test WHERE name = '?'";
executeUpdate(sql,"小狗");
}
/**
* 这个非DQl的测试,会在数据库获取一个List
* @throws Exception
*/
@Test
public void test1() throws Exception {
String sql = "SELECT * FROM test WHERE name = '?'";
List<User> userList = executeQuery(sql, User.class, "小狗");
}
}
注意
:User类在上述没有写出来,这个就行相应的数据库表 ,数据库表与对象一一对应。