JDBC是为了访问不同的数据库提供了统一接口,为使用者屏蔽了细节问题。
Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作
JDBC的基本原理图
JDBC是Java提供一套用于数据库操作的接口API,Java长序员只需要面向这套接口编程即可。不同的数据厂商,需要针对这套接口,提供不同的实现。
JDBC API是一系列的接口,它统一和规范了应用程序与数据库的连接、执行SQL语句,并得到返回结果等各类操作,相关类的接口在java.sql与javax.sql中
通过JDBC对表actor进行添加、删除和修改操作。
package khan.louis;
import com.mysql.cj.jdbc.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月13日19:46
*/
//第一个JDBC程序,完成简单的操作
public class TestJDBC01 {
public static void main(String[] args) throws SQLException{
//前置工作:在项目下创建一个文件夹,将mysql.jar拷贝到该目录下,点击add to libraries
/*导入JDBC的JAR包,可以在https://dev.mysql.com/downloads/file/?id=477058下载*/
//1.注册驱动,
Driver driver = new Driver();//创建driver对象
//2.得到连接
String url = "jdbc:mysql://127.0.0.1:3306/(数据库名)?serverTimezone=GMT&useSSL=false";
/* jdbc:mysql://是一个规定好的协议,通过jdbc的方式连接mysql
localhost ,表示本机的ip地址,也可以是其他ip
3306:端口号
testjdbc是表示连接的数据库名称*/
//mysql的连接的本质就是socket连接
//将用户名和密码封装到Properties对象中
Properties properties = new Properties();
properties.setProperty("user", "username");//用户名
properties.setProperty("password", "password");//密码
//获取连接
Connection connect = driver.connect(url, properties);
//3.执行操作
// String sql = "insert into actor(name, sex, borndate, phone) values('khan','女','1999-07-21','11111111111');";
String sql = "delete from actor where name = 'khan' and sex = '女';";
Statement statement = connect.createStatement();//可以执行sql语句,并返回其生成的对象
int rows = statement.executeUpdate(sql);//如果是dml语句,返回的就是影响的行数
System.out.println(rows > 0? "成功":"失败");
//4.关闭连接资源
statement.close();
connect.close();
}
}
使用com.mysql.jc.jdbc.Driver
package khan.louis;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月14日9:24
*/
//方式二:使用反射加载Driver类
public class TestJDBCTwo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射,动态加载,更加灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");//加载的是Driver的class对象
//我们可以转换为Driver对象
Driver driver = (Driver)aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/testjdbc?serverTimezone=GMT&useSSL=false";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "zkpk");
Connection connect = driver.connect(url, properties);
System.out.println("方式二" + connect);
//执行
String sql = "insert into actor(name, sex, borndate, phone) values('louis','男','1999-07-22','113111111');";;
Statement statement = connect.createStatement();
int result = statement.executeUpdate(sql);
System.out.println(result > 0? "成功":"失败");
//关闭
statement.close();
connect.close();
}
}
使用 DriverManager 替换Driver
package khan.louis.jdbc;
import java.sql.*;
/**
* @author XRY
* @date 2023年04月21日13:11
*/
//方式三:使用DriverManager代替Driver
public class TestJDBCThree {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射加载Driver
Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();
//创建url USER和password
String url = "jdbc:mysql://localhost:3306/testjdbc?serverTimezone=GMT&useSSL=false";
String user = "root";
String password = "zkpk";
//使用DriverManager代替Driver
DriverManager.registerDriver(driver);//注册驱动
//使用getConnection
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第三种方式:"+ connection);
//执行
String sql = "insert into actor(name, sex, borndate, phone) values('louis','男','1989-07-22','113111111');";;
Statement statement = connection.createStatement();
int result = statement.executeUpdate(sql);
System.out.println(result > 0? "成功":"失败");
//关闭
statement.close();
connection.close();
}
}
这种方式获取连接时使用最多的,推荐使用。
package khan.louis.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @author XRY
* @date 2023年04月21日14:11
*/
//方式四:使用Class.forName自动完成注册驱动,简化代码
public class TestJDBCFour {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//在加载Driver类时, 注册驱动自动完成。
/*
源码:
1.静态代码块,在类加载的时候,会执行一次DriverManager.registerDriver()
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}*/
Class.forName("com.mysql.cj.jdbc.Driver");//使用反射加载
//创建url 用户名和密码
String url = "jdbc:mysql://localhost:3306/testjdbc?serverTimezone=GMT&useSSL=false";
String user = "root";
String password = "zkpk";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第四种方式" + connection);
String sql = "insert into actor(name, sex, borndate, phone) values('louis','男','1989-07-22','113411111');";;
Statement statement = connection.createStatement();
int result = statement.executeUpdate(sql);
System.out.println(result > 0? "成功":"失败");
//关闭
statement.close();
connection.close();
}
}
注:在mysql1.5以后使用了jdbc4可以无需Class.forName(“com.mysql.jdbc.Driver”);注册驱动而是自动调用驱动jar包下的META-INF\services\java.sql.Driver文本中的类名称去注册。但建议还是写入。避免版本混淆。
package khan.louis.jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月21日14:50
*/
//方式五:添加配置文件,使连接更灵活
public class TestJDBCFive {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//在方式四的基础上增减配置文件,让链接mysql更加灵活
//通过properties对象获取相关配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\jdbc\\MySQL.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
url = url + "?serverTimezone=GMT&useSSL=false";
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("方式五" + connection);
}
}
//配置文件
user=root
password=root
url=jdbc:mysql://localhost:3306/testjdbc
driver=com.mysql.cj.jdbc.Driver
示例:使用方式五:
1、创建student
2、使用jdbc添加五条数据
3、修改id = 1的记录,将name改成自己的名字,
4、删除id = 3的记录
package khan.louis.self_testjdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月21日15:37
*/
public class TestStudent {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//引入properties文件
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\self_testjdbc\\student.properties"));
//获取文件中的内容
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
url = url + "?serverTimezone=GMT&useSSL=false";
//加载Driver类,
Class.forName(driver);
//连接
Connection connection = DriverManager.getConnection(url, user, password);
//执行操作使用jdbc添加五条数据
String sql = "insert into student(`id`, `name`, `age`) values (1, '可汗', 12),(2, '路易斯', 18), (3, '威登', 23), (4, 'louis', 12), (5, 'khan', 18)";
Statement statement = connection.createStatement();
int result = statement.executeUpdate(sql);
System.out.println(result > 0? "成功":"失败");
//修改id = 1的记录,将name改成自己的名字
String sql2 = "update student set `name` = 'sea' where `id` = 1;";
int result1 = statement.executeUpdate(sql2);
System.out.println(result1 > 0? "successful":"defeat");
//删除id = 3的记录
String sql3 = "delete from student where `id` = 3;";
int result4 = statement.executeUpdate(sql3);
System.out.println(result4 > 0?"成功":"失败");
//关闭连接
statement.close();
connection.close();
}
}
//配置文件
user=root
password=root
url=jdbc:mysql://localhost:3306/testjdbc
driver=com.mysql.cj.jdbc.Driver
注意:在这里,我直接先创建了数据表student,下面是sql语句.
use testjdbc;
create student(
id int primary key not null,
`name` varchar(10),
age int(3) not null
);
1、表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
2、ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。
3、next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。
package khan.louis.jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月23日8:41
*/
//测试select语句,返回ResultSet,并取出结果。
public class TestResultSet {
public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
//获取数据
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\jdbc\\TestResultSet.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//注册驱动
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
//操作语句
String sql = "select `name`, `age`,`id` from student";
//得到statement
Statement statement = connection.createStatement();
//使用executeQuery会返回一个结果集
ResultSet resultSet = statement.executeQuery(sql);
/*+--------+-----+----+
| name | age | id |
+--------+-----+----+
| sea | 12 | 1 |
| 路易斯 | 18 | 2 |
| louis | 12 | 4 |
| khan | 18 | 5 |
+--------+-----+----+
4 rows in set (0.02 sec)*/
//使用while循环取出数据
while(resultSet.next()){//让光标向后移动,如果没有更多行,则返回false
String name = resultSet.getString(1);//获取该行的第一列
int age = resultSet.getInt(2);//获取第二列
int id = resultSet.getInt(3);
System.out.println(name + "\t" + age + "\t" + id);
//结果
/*sea 12 1
路易斯 18 2
louis 12 4
khan 18 5*/
}
//关闭连接
resultSet.close();
statement.close();
connection.close();
}
}
1、Statement对象用于执行静态SQL语句并返回其生成的结果的对象
2、在连接建立后,需要对数据库进行访问时、执行命令或是SQL语句,可以通过
Statement(存在sql注入)
PreparedStatement(预处理)
CallableStatement(存储过程)
3、Statement对象执行SQL语句,存在SQL注入风险
SQL注入:是指利用某些系统没有对用户输入的内容进行充分的调查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。
sql_injection.sql
想要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了。
use testjdbc;
-- SQL注入示例
create table test(
`name` varchar(10) not null UNIQUE,
`pwd` varchar(18) not null default ' ')character set utf8;
-- 添加数据
insert into test values('louis', '121212');
-- 查询某个管理员是否存在(正常)
select * from test where name = 'louis' and pwd = '121212';
-- sql注入
-- 输入用户名为 1' OR
-- 输入密码为 or '1' = '1
select * from test where name = '1' OR' AND pwd = ' OR '1' = '1';
-- 结果
louis 121212
package khan.louis.jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日10:37
*/
//测试statement注入问题
public class TestInjectSQL {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//让用户输入管理员名和密码
Scanner scanner = new Scanner(System.in);
System.out.println("请输入管理员的名字!!");
String test_name = scanner.nextLine();//使用next()会在空格处切断
System.out.println("请输入密码!!");
String test_pwd = scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\jdbc\\TestResultSet.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
/*sql语句*/
String sql = "select `name`, `pwd` from test where `name` = '"+ test_name + "' and pwd = '"+test_pwd+"';";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if(resultSet.next()){//如果查询到记录,则说明该用户存在
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
//结果
/*1.
* 正常输入:
*请输入管理员的名字!!
louis
请输入密码!!
121212
登录成功!
*
* 2.注入
* 请输入管理员的名字!!
1' or
请输入密码!!
or '1' = '1
登录成功!
* */
//关闭连接
resultSet.close();
statement.close();
connection.close();
}
}
为了解决Statement的注入问题,我们可以使用PreparedStatement代替。
1、PreparedStatement执行的SQL语句中的参数用?来表示,调用PreparedStatement对象的setXXX()方法来设置这些参数。setXXX()方法有两个参数,第一个参数是要设置的SQL语句中的索引(从1开始),第二个是设置的SQL语句中的参数的值。
String sql = "select count(1) from test where name = ? and pwd = ?;"
2、调用executeQuery(),返回ResultSet对象。
3、调用executeUpdate();执行更新,包括增、删、修改。返回的是一个int,影响的行数。
预处理的好处:
1、不再使用+拼接sql语句,减少语法错误。
2、有效的解决了sql注入的问题。
3、大大减少了编译次数,效率提高。
package khan.louis.jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日13:09
*/
//测试PreparedStatement使用
public class TestPreparedStatement {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//让用户输入管理员名和密码
Scanner scanner = new Scanner(System.in);
System.out.println("请输入管理员的名字!!");
String test_name = scanner.nextLine();//使用next()会在空格处切断
System.out.println("请输入密码!!");
String test_pwd = scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\jdbc\\TestResultSet.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
/*sql语句 sql语句中的?相当于占位符*/
String sql = "select `name`, `pwd` from test where `name` = ? and pwd = ?;";
//preparedStatement对象实现了PreparedStatement接口的实现类的对象。
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//给?赋值
preparedStatement.setString(1, test_name);
preparedStatement.setString(2, test_pwd);
// Statement statement = connection.createStatement();
//执行select语句。
ResultSet resultSet = preparedStatement.executeQuery();
//在上面已经关联过了,所以在执行的时候不需要再写,要是写入就是带?的内容
if(resultSet.next()){//如果查询到记录,则说明该用户存在
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
/*
* 1、正常输入
* 请输入管理员的名字!!
louis
请输入密码!!
121212
登录成功!
* 2、注入
* 请输入管理员的名字!!
1' or
请输入密码!!
or '1' = '1
登录失败!
* */
//关闭连接
resultSet.close();
preparedStatement.close();
connection.close();
}
}
package khan.louis.jdbc;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日18:16
*/
public class TestExecuteUpdate {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//让用户输入管理员名和密码
Scanner scanner = new Scanner(System.in);
System.out.println("请输入管理员的名字!!");
String test_name = scanner.nextLine();//使用next()会在空格处切断
System.out.println("请输入密码!!");
String test_pwd = scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\jdbc\\TestResultSet.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
/*添加记录*/
String sql = "insert into test values(?, ?)";
//preparedStatement对象实现了PreparedStatement接口的实现类的对象。
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//给?赋值
preparedStatement.setString(1, test_name);
preparedStatement.setString(2, test_pwd);
// Statement statement = connection.createStatement();
//执行select语句。
int result = preparedStatement.executeUpdate();
System.out.println(result>0?"成功":"失败");
/*请输入管理员的名字!!
khan
请输入密码!!
1234
成功*/
//关闭连接
preparedStatement.close();
connection.close();
}
}
1、创建demo表使用PreparedStatement添加5条数据
2、 修改Alex的记录,将name 改为king
3、删除一条记录
4、查询全部记录,并显示在控制台
package khan.louis.self_testjdbc;
import javax.swing.text.AbstractDocument;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日18:30
*/
public class TestPreparedStatement {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
content c = new content();
Scanner scanner = new Scanner(System.in);
//1、读取数据
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\self_testjdbc\\TestPreparedStatement.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//2、注册驱动
Class.forName(driver);
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//4、sql语句
String sql = "insert into demo values(?,?,?)";
//5、创建preparedStatement对象
PreparedStatement preparedStatement = null;
int result = 0;
for (int i = 0; i < 3; i++) {
preparedStatement = connection.prepareStatement(sql);
System.out.println("请输入id");
c.setId(scanner.nextInt());
System.out.println("请输入姓名");
c.setName(scanner.next());
System.out.println("请输入性别");
c.setGender(scanner.next());
preparedStatement.setInt(1, c.getId());
preparedStatement.setString(2, c.getName());
preparedStatement.setString(3, c.getGender());
result = preparedStatement.executeUpdate();
}
//查看结果
System.out.println(result>0?"成功":"失败");
//断开连接
preparedStatement.close();
connection.close();
}
}
//定义输入内容
class content{
private int id;
private String name;
private String gender;
public content() {
}
public content(int id, String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
//sql语句
use testjdbc;
create table demo(
id int primary key not null,
`name` varchar(10),
`age` varchar(3),
`gender` char(1)
);
alter table demo drop column age;
select * from demo;
结果
package khan.louis.self_testjdbc;
import javax.swing.text.AbstractDocument;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日18:30
*/
public class TestPreparedStatement {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要修改姓名");
String name1 = scanner.next();
System.out.println("请输入改为姓名");
String name2 = scanner.next();
//1、读取数据
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\self_testjdbc\\TestPreparedStatement.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//2、注册驱动
Class.forName(driver);
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//4、sql语句
String sql = "update demo set `name` = ? where `name` = ?;";
//5、创建preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, name2);
preparedStatement.setString(2, name1);
int result = preparedStatement.executeUpdate();
//查看结果
System.out.println(result>0?"成功":"失败");
//断开连接
preparedStatement.close();
connection.close();
}
}
结果
package khan.louis.self_testjdbc;
import javax.swing.text.AbstractDocument;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日18:30
*/
public class TestPreparedStatement {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要修改姓名");
String name1 = scanner.next();
//1、读取数据
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\self_testjdbc\\TestPreparedStatement.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//2、注册驱动
Class.forName(driver);
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//4、sql语句
String sql = "delete from demo where `name` = ?";
//5、创建preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, name1);
int result = preparedStatement.executeUpdate();
//查看结果
System.out.println(result>0?"成功":"失败");
//断开连接
preparedStatement.close();
connection.close();
}
}
/*
请输入要修改姓名
Jet
成功*/
package khan.louis.self_testjdbc;
import javax.swing.text.AbstractDocument;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author XRY
* @date 2023年04月23日18:30
*/
public class TestPreparedStatement {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//1、读取数据
Properties properties = new Properties();
properties.load(new FileInputStream("JDBc\\src\\khan\\louis\\self_testjdbc\\TestPreparedStatement.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//2、注册驱动
Class.forName(driver);
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//4、sql语句
String sql = "select * from demo;";
//5、创建preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();
//查看结果
while(resultSet.next()){
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
String gender = resultSet.getString(3);
System.out.println(id + "\t" + name + "\t" + gender);
}
//断开连接
resultSet.close();
preparedStatement.close();
connection.close();
}
}
//结果:
/*1 khan 男
2 Louis 男
3 king 中
4 KhanLouis 女*/
在JDBC操作中,获取连接和释放资源是经常使用到的,可以将其封装JDBC连接的工具类JDBCUtils。
package khan.louis.jdbc.jdbcutils;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月24日7:33
*/
//这是一个工具类,完成mysql的连接和关闭资源
public class JDBCUtils {
//定义相关的属性(4个),因为只需要一份,因此我们做出static
private static String user;//用户名
private static String password;//密码
private static String url;//url
private static String driver;//驱动名
//在static代码块去初始化
static{
Properties properties = new Properties();
try {
properties.load(new FileInputStream("JDBc\\khan\\louis\\jdbc\\jdbcutils\\JDBCUtils.properties"));
///读取相关的属性值
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//连接数据库, 返回Connection
public static Connection getConnection(){
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//关闭资源
/*
* 1.ResultSet 结果集
* 2、Statement或者PreparedStatement
* 3.Connection
* 4.如果需要关闭资源,就传入对象,否则就传入null*/
public static void close(ResultSet set, Statement statement, Connection connection){
//判断是否为空
try {
if(set != null){
set.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
package khan.louis.jdbc.jdbcutils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @author XRY
* @date 2023年04月24日7:57
*/
//测试JDBCUtils工具类,完成DML 和 SELECT
public class TestJDBCUtils {
public static void main(String[] args) {
TestJDBCUtils testJDBCUtils = new TestJDBCUtils();
testJDBCUtils.testDML();
}
public void testDML(){
//DML主要是insert, update, delete
//1、得到链接
Connection connection = null;
//2、组织sql
String sql = "update demo set `name` = ? where id = ?";
//3、创建PreparedStatement对象
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
//给占位符赋值
preparedStatement.setString(1,"Alex");
preparedStatement.setInt(2, 4);
//执行
int result = preparedStatement.executeUpdate();
System.out.println(result>0? "成功":"失败");
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtils.close(null, preparedStatement, connection);
}
}
}
//结果
/*
成功*/
1、JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能将回滚。
2、JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务。
3、调用Connection的setAutoCommit(false)可以取消自动提交事务
4、在所有的SQL语句都成功执行后,调用commit();方法提交事务
5、在其中某个操作失败或出现异常的时候,调用rollback();方法回滚事务。
package khan.louis.jdbc.transaction;
import khan.louis.jdbc.jdbcutils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author XRY
* @date 2023年04月24日13:08
*/
public class NoTransaction {
public void testDML(){
//获得连接
Connection connection = JDBCUtils.getConnection();
PreparedStatement preparedStatement = null;
//创建sql语句
String sql = "update account set money = money - 100 where `name` ='khan'";
String sql2 = "update account set money = money + 100 where `name` ='louis'";
try {
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();//执行第一条sql
int i = 1 /0;//抛出异常导致数据不一致
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtils.close(null, preparedStatement, connection);
}
}
}
public void testDMLTran(){
//获得连接
Connection connection = null;
PreparedStatement preparedStatement = null;
//创建sql语句
String sql = "update `account` set money = money - 100 where `name` ='khan'";
String sql2 = "update account set money = money + 100 where `name` ='louis'";
try {
connection = JDBCUtils.getConnection();
connection.setAutoCommit(false);
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();//执行第一条sql
int i = 1 /0;//抛出异常导致数据不一致
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
connection.commit();
} catch (Exception e) {
//这里我们可以进行回滚,即撤销执行的sql,默认回滚到事务开始的地方
System.out.println("执行发生了异常,撤销执行的sql");
try {
connection.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
} finally {
JDBCUtils.close(null, preparedStatement, connection);
}
}
1、当需要成批插入或者更新记录时,可以采用Java的批量处理更新机制,这一机制允许许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效率。
2、JDBC的批量处理语句包括下面的方法:
方法 | 说明 |
---|---|
addBatch() | 添加需要批量处理的SQL语句或参数 |
executeBatch() | 执行批量处理语句 |
clearBatch() | 清空批处理包的语句 |
3、JDBC连接MySQL时,如果需要使用批处理功能,请再url中加参数:
?rewriteBatchedStatements = true
4、批处理往往和PreparedStatement一起搭配使用,可以即减少编译次数,又减少运行次数,效率大大提高。
向student表中添加5000条数据,对比使用批处理和正常处理耗时分别多久
package khan.louis.jdbc.batch;
import khan.louis.jdbc.jdbcutils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @author XRY
* @date 2023年04月24日20:22
*/
//演示java的批处理
public class Batch_ {
//传统方法,添加5000条数据到student中
@Test
public void noBatch() throws Exception {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into student(id, name, age) values(?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
preparedStatement.setInt(1,i+10);
preparedStatement.setString(2,"Louis" + i);
preparedStatement.setString(3,"1688");
preparedStatement.executeUpdate();
}
System.out.println("结束执行");
long end = System.currentTimeMillis();
System.out.println("传统方法耗时+"+ (end-start));
//关闭连接
JDBCUtils.close(null, preparedStatement, connection);
}
//结果:
/*开始执行
结束执行
传统方法耗时+4003*/
//使用批量方式添加数据
@Test
public void batch() throws Exception {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into student(id, name, age) values(?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
preparedStatement.setInt(1,i+10);
preparedStatement.setString(2,"Louis" + i);
preparedStatement.setString(3,"1688");
//将sql语句加入到批处理包中
preparedStatement.addBatch();
//当有有1000条记录时,批量执行
if((i + 1) %1000 == 0){//满1000条数据
preparedStatement.executeBatch();
//清空
preparedStatement.clearBatch();
}
}
System.out.println("结束执行");
long end = System.currentTimeMillis();
System.out.println("批量方式耗时+"+ (end-start));
//关闭连接
JDBCUtils.close(null, preparedStatement, connection);
}
//结果
/*开始执行
结束执行
批量方式耗时+138*/
}
注意:需要在url后加入?rewriteBatchedStatements = true
1、传统的JDBC数据库连接使用DriverManager来获取, 每次向数据库建立连接的时候都要讲Connection加载到内存中,再验证IP地址,用户名和密码(0.05-1s时间)需要数据库连接的时候,就像数据库要求一个,频繁的进行数据库的连接操作将占用很多的系统资源,容易造成服务器崩溃。
2、每一次数据库连接,使用后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄露,最终导致重启数据库
3、传统获取连接得方法,不能控制创建的创建的连接数量,如果连接过多,也可能导致内存泄漏,MySQL崩溃。
4、解决传统开发中的数据库连接问题,可以采用数据库连接池技术(connection pool)
使用数据库连接池可以解决上述存在的问题。
1、预先在缓冲区中放入一定数量的连接,当需要建立数据库连接时,中需要从"缓冲区中取出一个"使用完毕之后再放回去(将引用取消)。
2、数据库连接池负责分配,管理和释放数据库连接,而不是重新建立一个。
3、当应用程序向连接池请求的来连接数量超过最大连接数量时,这些请求将被加入到等待队列。
JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现[提供相应的jar包]。
名称 | 特点 |
---|---|
C3P0数据库连接池 | 速度相对较慢,稳定性不错(hibernate,spring) |
DBCP数据库连接池 | 速度相对C3P0较快,但不稳定 |
Proxool数据库连接池 | 有监控连接池的功能,稳定性较C3P0差一点 |
BoneCP数据库连接池 | 速度快 |
Druid(德鲁伊)数据库连接池 | 它是阿里提供的,集DBCP,C3P0,Proxool优点于一身的数据库连接池。 |
package khan.louis.jdbc.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月25日16:16
*/
//演示c3p0的使用
public class TestC {
//方式1:相关参数,在程序中指定user url password等
@Test
public void testC3P0_01() throws Exception {
//1.创建一个数据源对象
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//2.通过配置文件mysql.properties获取相关的连接信息
Properties properties = new Properties();
properties.load(new FileInputStream("JDBCUtils.properties"));
///读取相关的属性值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//给数据源comboPooledDateSource 设置相关的参数,
//连接管理是由comboPooledDateSource 来管理
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
//设置数据源的连接数
//初始化连接数
comboPooledDataSource.setInitialPoolSize(10);
//最大连接数
comboPooledDataSource.setMaxPoolSize(50);
Connection connection = comboPooledDataSource.getConnection();//这个方法就是从DataSource接口实现
System.out.println("连接成功!!");
connection.close();
}
}
此外还可以使用配置文件的方式来连接 。
package khan.louis.jdbc.druid;
import com.alibaba.druid.pool.DruidAbstractDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月25日18:19
*/
public class TestDruid {
@Test
public void testDruid() throws Exception {
//1、加入Druid jar包
//2、加入配置文件,将该文件拷贝到项目的src目录
//3、创建properties对象用来读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
//4、创建一个指定参数的数据库连接池, Druid数据库连接池
// DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// Connection connection = dataSource.getConnection();
// System.out.println("连接成功");
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//5、测试效率
System.out.println("开始测试");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = dataSource.getConnection();
connection.close();
// System.out.println("连接成功");
}
long end = System.currentTimeMillis();
System.out.println("Druid连接池 耗时==》" + (end - start));
/*开始测试
4月 25, 2023 6:51:42 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Druid连接池 耗时==》365*/
}
}
package khan.louis.jdbc.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月25日19:16
*/
//基于Druid数据库连接池的工具类
public class DruidUtils {
private static DataSource ds;
//在静态代码块完成ds的初始化
static{
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//编写getConnection()
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//关闭连接, 在数据库连接池中, close不是真的断开连接,只是将connection放回到连接池中
public static void close(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection){
try {
if(resultSet != null){
resultSet.close();
}
if(preparedStatement != null){
preparedStatement.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
在以前的使用方法中关闭connection后,resultSet结果集无法使用,resultSet不利于数据的管理(只能使用一次), 使用返回的信息也不方便。
1、commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。
1、QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理
2、使用QueryRunner类实现查询
3、ResutSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换成另一种形式。
对象 | 作用 |
---|---|
ArrayHandler | 把结果集中的第一行数据转成对象数组 |
ArrayListHandler | 把结果集中的没一行数据都转成一个数组,再存到List中 |
BeanHandler | 将结果集中的第一行数据封装到一个对应的JavaBean实例中 |
BeanListHandler | 将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放放到List里 |
ColumnListHandler | 将结果集中某一列的数据存放到List中 |
KeyedHandler(name) | 将结果集中的每行数据都封装到Map里,再把这些Map再存到一个map里,其key为指定的key |
MapHandler | 将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值 |
MapListHandler | 将结果集中的每一行数据都封装到一个Map里,然会再存放到List |
package khan.louis.jdbc.druid;
import khan.louis.jdbc.jdbcutils.JDBCUtils;
import khan.louis.jdbc.jdbcutils.TestJDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @author XRY
* @date 2023年04月25日20:29
*/
public class TestDBUtils {
//使用apache-DBUtils 工具类 + Druid完成对表的crud操作
@Test
public void testQueryMany() throws SQLException {
//返回结果是多行的情况
//1、得到连接
Connection connection = DruidUtils.getConnection();
//2、使用DBUtils的类和接口
//2.1、引入DBUtils相关的jar文件
//2.2、创建QueryRunner
QueryRunner queryRunner = new QueryRunner();
//3、就可以执行相关的方法,返回ArrayList结果集
//3.1、定义查询语句
String sql = "select * from student where id = ?";
/*query方法就是执行sql语句,得到resultset --- 封装到ArrayList集合中
* 返回集合
* connection:连接
* 执行sql语句
* new BeanListHandler<>(Student.class):在将resultset取出弄成一个Student对象,封装到ArrayList
* (使用Student.class的原因是,以上的对象底层会使用到反射机制,查看获取Student类的属性,然后进行封装)
* 1 就是给sql语句中的?赋值的,可以有多个值,因为是可变参数*/
//底层得到的resultset会在query关闭, 还会关闭preparedStatement
List<Student> list = queryRunner.query(connection, sql, new BeanListHandler<>(Student.class), 400);
System.out.println("输出结合的信息");
for(Student student:list){
System.out.println(student);
}
//释放资源
DruidUtils.close(null,null, connection);
}
}
//结果:
/*4月 25, 2023 9:01:16 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
输出结合的信息
Student{id=400, name='Louis390', age=1688}*/
@Test
public void testQuerySingle() throws SQLException {
//1、得到连接
Connection connection = DruidUtils.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "select * from Student where id = ?";
//返回单个对象,使用的Handler是BeanHandler
Student query = queryRunner.query(connection, sql, new BeanHandler<>(Student.class), 100);
System.out.println(query);
//释放资源
DruidUtils.close(null, null, connection);
//结果
/*4月 26, 2023 8:54:51 上午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Student{id=100, name='Louis90', age=1688}*/
}
@Test
public void testDML() throws SQLException {
//1、得到连接
Connection connection = DruidUtils.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "update student set name = ? where id = ?";
//返回单个对象,使用的Handler是BeanHandler
int row = queryRunner.update(connection, sql, "louis300", 300);
//执行DML操作执行的方法是update,返回值是受影响的行数
System.out.println(row > 0?"执行成功":"执行没有影响到行数");
//释放资源
DruidUtils.close(null, null, connection);
//结果
/*4月 26, 2023 9:07:24 上午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
执行成功*/
}
1、SQL语句是固定的,不能够通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
2、对于select操作,若果有返回值,返回类型不能固定,需要使用泛型
3、将来的表很多,业务需求复杂,不可能只靠一个Java类完成。
DAO:data access object(数据访问对象)
以Student表为例
我们新建如下的目录结构:
package khan.louis.jdbc.dao.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author XRY
* @date 2023年04月25日19:16
*/
//基于Druid数据库连接池的工具类
public class DruidUtils {
private static DataSource ds;
//在静态代码块完成ds的初始化
static{
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);//DataSource类型
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//编写getConnection()
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//关闭连接, 在数据库连接池中, close不是真的断开连接,只是将connection放回到连接池中
public static void close(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection){
try {
if(resultSet != null){
resultSet.close();
}
if(preparedStatement != null){
preparedStatement.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
//注意src\\druid.properties包含的是你的连接信息附件,可将德鲁伊的附件导入到文件中,修改相关参数即可
package khan.louis.jdbc.dao.domain;
/**
* @author XRY
* @date 2023年04月25日20:42
*/
public class Student {
private Integer id;
private String name;
private Integer age;
public Student(){
}
public Student(Integer id, String name, Integer age){
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
//studdent表
create table student(
id int primary key,
`name` varchar(10) not null,
age int(10) not null
);
package khan.louis.jdbc.dao.basicdao;
import khan.louis.jdbc.druid.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
/**
* @author XRY
* @date 2023年04月26日18:51
*/
//开发BasicDao是其他DAO的父类
//BasicDao表示一个泛型,之后在使用的时候就可以确定那个类操作这个泛型, 泛型指定具体的类型
public class BasicDao<T> {
private QueryRunner qr = new QueryRunner();
//开发通用的dml方法,针对任意的表
public int update(String sql, Object... parameters){
//拿到了sql语句,所以我们需要一个连接
Connection connection = null;
//通过Druid找到连接
try {
connection = DruidUtils.getConnection();
int update = qr.update(connection, sql, parameters);
return update;//返回受影响的行数
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
DruidUtils.close(null, null, connection);
}
}
//返回多个对象,即查询的结果是多行,针对任意表
/**
*
* @param sql--->sql语句, 可以有?
* @param clazz---->传入一个Class对象 比如Student.class
* @param parameters--->传入?的具体值,可以是多个
* @return --->更具class 返回对应的ArrayList结合
*/
public List<T> queryMulti(String sql, Class<T> clazz, Object...parameters){
Connection connection = null;
try {
connection = DruidUtils.getConnection();
List<T> query = qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
return query;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
DruidUtils.close(null, null, connection);
}
}
//查询单行的通用方法
public T querySingle(String sql, Class<T> clazz, Object... parameters){
Connection connection = null;
try {
connection = DruidUtils.getConnection();
T query = qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);
return query;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
DruidUtils.close(null, null, connection);
}
}
//查询单行单例的方法,即返回单值的方法
public Object queryScalar(String sql, Object... parameters){
Connection connection = null;
try {
connection = DruidUtils.getConnection();
return qr.query(connection, sql, new ScalarHandler(), parameters);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
DruidUtils.close(null, null, connection);
}
}
}
package khan.louis.jdbc.dao.basicdao;
import khan.louis.jdbc.dao.basicdao.BasicDao;
import khan.louis.jdbc.dao.domain.Student;
/**
* @author XRY
* @date 2023年04月26日19:30
*/
public class StudentDao extends BasicDao<Student> {
//1.Student继承了BasicDao的方法
//2.根据业务需求,可以编写特有的方法
}
package khan.louis.jdbc.dao.test;
import khan.louis.jdbc.dao.basicdao.StudentDao;
import khan.louis.jdbc.dao.domain.Student;
import org.junit.Test;
import java.util.List;
/**
* @author XRY
* @date 2023年04月26日19:33
*/
//测试StudentDao对student的crud操作
public class TestStudentDao {
@Test
public void testStudentDao(){
StudentDao studentDao = new StudentDao();
//1.查询
List<Student> students = studentDao.queryMulti("select * from student where id > ? and id < ?", Student.class, 200, 205);
for(Student stu:students){
System.out.println(stu);
}
//2.查询单条记录
Student student = studentDao.querySingle("select * from student where id = ?", Student.class, 100);
System.out.println(student);
//3.查询单行单列
Object result = studentDao.queryScalar("select name from student where id = ?", 500);
System.out.println(result);
//4.dml操作
int Rresult = studentDao.update("insert into student values(?,?,?)", 1, "louis", 35);
System.out.println(Rresult > 0?"执行成功":"执行没有影响表");
}
}