目录
关于JDBC
什么是JDBC?
Java DataBase Connectivity (Java语言连接数据库)
JDBC的本质是什么?
JDBC是SUN公司制定的一套接口(interface)
java.sql.*;(这个软件包下有很多接口。)
JDBC开发前的准备工作
JDBC开发前的准备工作,先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
classpath=.;D:\JDBC\MySQL\mysql-connector-java-5.1.37-bin.jar
以上的配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以上的环境变量。
DEA有自己的配置方式。
JDBC编程六步(需要背会)
第一步: 注册驱动 (作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
第二步: 获取连接 (表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道)
第三步: 获取数据库操作对象 (专门执行sq1语句的对象)
第四步: 执行SQL语句 (DQL DML.... )
第五步: 处理查询结果集 (只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
第六步: 释放资源 使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
代码实战
举例一(注册驱动方法1 , JDBC完成insert)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
JDBC 编程六步
1. 注册驱动
java.sql.Driver driver = new com.mysql.jdbc.Driver(); // java.sql.Driver dirver抽象接口 com.mysql.jdbc.Driver实现类 ; 多态,父类的引用指向子类的对象
java.sql.DriverManager.registerDriver(driver) Java的sql包下的用于管理一组JDBC驱动程序的基本服务的类的registerDriver()静态方法完成注册
2. 建立连接
Connection connection = DriverManager.getConnection(url,user,password); DriverManager类中的getConnection建立与给定数据库URL的连接,返回一个Connection(连接对象)com.mysql.jdbc.JDBC4Connection@6d21714c。
3. 获取数据库对象
Statement statement = connection.createStatement(); 调用步骤二返回的数据库对象的createStatement方法返回一个Statement对象(Statement用于执行静态SQL语句并返回其生成的结果的对象)
4. 执行SQL
int count = statement.executeUpdate(sql); 调用statement对象的executeUpdate方法,执行给定的SQL语句(INSERT、UPDATE、DELETE )
5. 如果第四步执行的是SELECT语句,这一步便是处理结果集
6. 释放资源
为了保证资源一定释放,将把close()操作放在finally中 statement.close(),connection.close(),并且要遵循从小到大依次关闭。
*/
public class JDBCTest01 {
public static void main(String[] args) {
Statement statement=null;
Connection connection=null;
try{
java.sql.Driver driver = new com.mysql.jdbc.Driver(); // java.sql.Driver dirver抽象接口 com.mysql.jdbc.Driver实现类 ; 多态,父类的引用指向子类的对象
java.sql.DriverManager.registerDriver(driver);
String url="jdbc:mysql://localhost:13306/atguigudb2";
String user="root";
String password="123456";
connection = DriverManager.getConnection(url,user,password); // java.sql.Connection接口 Connection对象的数据库能够提供描述其表,其支持的SQL语法,其存储过程,此连接的功能等的信息。 该信息是用getMetaData方法获得的。
System.out.println("数据库连接对象="+ connection); // 数据库连接对象=com.mysql.jdbc.JDBC4Connection@6d21714c
statement = connection.createStatement(); // Statement 专门执行sql语句
String sql="INSERT INTO emp32 VALUES(1)";
int count = statement.executeUpdate(sql);// 执行给定的SQL语句的方法,专门执行DML语句的(insert delete update),返回值是"影响数据库中的记录条数"
System.out.println(count==1 ? "保存成功" : "保存失败");
}catch (SQLException e){
e.printStackTrace();
}finally {
// 释放资源
// 为了保证资源一定释放,在finally语句块中关闭资源,并且要遵循从小到大依次关闭,分别对其try..catch
try {
if(statement!=null){
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
举例二 (JDBC完成delete)
import java.sql.*;
/*
JDBC完成delete
1、注册驱动
2、建立数据库连接
3、获取数据库对象
4、执行SQL
5、如果第四步执行的是SELECT语句,则会有此步,应为处理结果集
6、释放资源
*/
public class JDBCTest02 {
public static void main(String[] args) {
Statement statement=null;
Connection connection=null;
try {
java.sql.Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
String url="jdbc:mysql://localhost:13306/atguigudb2";
String user="root";
String password="123456";
connection = DriverManager.getConnection(url,user,password);
System.out.println(connection);
statement = connection.createStatement();
String sql=" DELETE FROM emp1 WHERE id=0 ";
int count = statement.executeUpdate(sql);
System.out.println(count==1 ? "操作成功" : "操作失败");
}catch (SQLException e){
e.printStackTrace();
}finally {
try {
if(statement !=null){
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
举例三(注册驱动方法2)
①通过查看com.mysql.jdbc.Driver类的源码发现,可以利用反射的机制(Classs.forName此方法的执行会导致类的加载)从而使类中的静态代码块执行(这个代码块便是注册驱动的操作)
②将连接数据库的所有信息配置到配置文件中
import sun.security.util.Password;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
/*
注册驱动的另一种方式(常用)
将连接数据库的所有信息配置到配置文件中
1、注册驱动
2、创建连接
3、获取数据库对象
4、执行SQL
5、如果步骤4执行的是SELECT语句,则应有此步骤,为处理结果集
6、释放资源
*/
public class JDBCTest03 {
public static void main(String[] args) {
//使用资源绑定器绑定属性配置文件
ResourceBundle bundle = ResourceBundle.getBundle("jdbc03");
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");
Connection connection=null;
Statement statement=null;
try {
//注册驱动第一种写法
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//注册驱动方法二( 常用,因为参数是字符串,而字符串可以写到xxx.properties(配置文件)中) (以下方法不需要接受返回值,我们只是想用它的类加载动作)
//通过查看com.mysql.jdbc.Driver类的源码发现,可以利用反射的机制(Classs.forName此方法的执行会导致类的加载)从而使类中的静态代码块执行(这个代码块便是注册驱动的操作)
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
statement = connection.createStatement(); // createStatement()
String sql = " insert into atguigudb2.emp1 values (12,'鱼仔',now()) ";
int count = statement.executeUpdate(sql);
System.out.println(count==1 ?"操作成功" :"操作失败" );
}catch (SQLException e){
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
if(statement!=null){
statement.close();
}
}catch (SQLException e ){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
/* jdbc03.properties */
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:13306/atguigudb2
user=root
password=123456
举例四(处理结果集)
import java.sql.*;
import java.util.ResourceBundle;
/*
处理查询结果集
1、注册驱动
2、建立连接
3、获取数据库对象
4、执行SQL
5、若第四步执行的是SELECT,则此步为处理结果集
6、释放资源
*/
public class JDBCTest04 {
public static void main(String[] args) {
//将数据库信息绑定在配置文件
ResourceBundle resourceBundle=ResourceBundle.getBundle("JDBC04");
String driver = resourceBundle.getString("driver");
String url = resourceBundle.getString("url");
String user = resourceBundle.getString("user");
String password = resourceBundle.getString("password");
Connection connection=null;
Statement statement =null;
ResultSet resultSet=null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url,user,password);
System.out.println(connection);
statement = connection.createStatement();
// int executeUpdate (insert/delete/update)
// ResultSet executeQuery (select)
String sql=" select id i,name n,hire_date h from atguigudb2.emp1 ";
resultSet = statement.executeQuery(sql); // executeQuery()方法,通常参数为静态SQL SELECT语句,返回一个ResultSet对象。
//处理结构集
// next()方法,移动光标到行前,依次往下,有数据返回ture,无数据返回false。
// getString()方法,检索当前行中指定列的值ResultSet对象为String的值并返回,参数为列的下标数(从1开始)
// ,但使用下标,使程序并不健壮,建议使用字段名获取。
// while (resultSet.next()){
// String id_name=resultSet.getString(1);
// String name_name=resultSet.getString(2);
// String date_name=resultSet.getString(3);
// System.out.println(id_name+","+name_name+date_name);
// }
// 建议: 此写法不是以列的下标获取,而是以列的名字获取。
/* while (resultSet.next()){
String id_name=resultSet.getString("i");
String name_name=resultSet.getString("n");
String date_name=resultSet.getString("h");
System.out.println(id_name+","+name_name+date_name);
}
*/
// 除了可以以String类型取出之外,还可以以特定的类型取出。
while (resultSet.next()){
int id_name=resultSet.getInt("i");
String name_name=resultSet.getString("n");
String date_name=resultSet.getString("h");
System.out.println(id_name+","+name_name+date_name);
}
}catch (SQLException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}finally {
try {
if (resultSet!=null){
resultSet.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (statement!=null){
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
/* JDBC04.properties */
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:13306/atguigudb2
user=root
password=023156
IDEA配置驱动
新建工程:
File - New - Project - Empty Project(空的工程) - NEXT - Project name(工程名称) - project location(工程文件存放路径) - Finish - OK - New Window 。
新建模块:
File - New - Module - Java - NEXT - Module name - Finish 。
导入驱动:
右键模块 - Open Module Settings - Libraries - + - Java - 选择jar包(驱动) - Choose Modules(导入哪个模块中) - Apply - Ok。
PowerDesigner16.5安装
NEXT - NEXT - 选择People R…China(PRC),然后选择我同意协议-
更改路径
根据自己需要选择,也可以全选
根据自己需要选择,这里选择全选
直接下一步
继续下一步
等待安装
功能实现
模拟用户登录 (sql注入)
/*
实现功能:
1、需求:
模拟用户登录的功能的实现。
2、业务描述:
程序运行的时候吗,提供一个输入的入口,可以让用户输入用户名和密码
用户输入用户名和密码之后,提交信息,java程序收集到用户信息
Java程序连接数据库验证用户名和密码是否合法
合法:显示登录成功
不合法:显示登录失败
3、数据准备:
在实际开发中,表的设计会使用专业的建模工具,我们这里安装一个建模工具: PowerDesigner
使用PD工具来进行数据库表的设计。(参见user-login.sql脚本)
4、当前程序存在问题:
用户名:fdsa
密码:fdsa' or '1'='1
登陆成功
这种现象被成为SQL注入(安全隐患)。 多年前黑客常用
5、导致SQL注入的根本原因是什么?
用户输入的信息中含有sq1语句的关键字,并且这些关键字参与sq1语句的编译过程,
导致sql语句的原意被扭曲,进而达到sql注入。
注册驱动
建立连接
获取数据库对象
执行SQL
处理结果集
释放资源
*/
import com.mysql.jdbc.Driver;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JDBCTest05 {
public static void main(String[] args) {
//初始化一个界面
Map<String,String> userLoginInfo=initUI();
//验证用户名和密码
boolean loginSuccess = login(userLoginInfo);
//输出结果
System.out.println(loginSuccess ? "登陆成功": "登录失败");
}
/**
*用户登录
* @param userLoginInfo 用户登录信息
* @return false表示失败,true表示成功
*/
private static boolean login(Map<String, String> userLoginInfo) {
//打标记的意识
boolean loginSuccess = false;
//JDBC代码
Connection connection = null;
Statement statement = null;
ResultSet resultSet=null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2", "root", "123456");
//获取数据库对象
statement= connection.createStatement();
//执行SQL
String sql="select * from t_user where login_name='"+userLoginInfo.get("loginName")+"' and login_password='"+userLoginInfo.get("loginPwd")+"'";
//以上正好完成了sq1语句的拼接,以下代码的含义是,发送sq1语句给DBMS, DBMs进行sq1编译。
//正好将用户提供的“非法信息"编译进去。导致了原sq1语句的含义被扭曲了。
resultSet = statement.executeQuery(sql);
//处理结果集
if(resultSet.next()){
//登录成功
loginSuccess=true;
}
//释放资源
}catch(ClassNotFoundException e){
e.printStackTrace();
}catch (SQLException e){
e.printStackTrace();
}finally {
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();
}
}
}
return loginSuccess;
}
/**
* 初始化用户界面
* @return 用户输入的用户名和密码等登录信息
*/
private static Map<String, String> initUI() {
Scanner scanner = new Scanner(System.in);
System.out.println("用户名: ");
String loginName = scanner.nextLine(); // nextLine() 读取整行数据
System.out.println("密码: ");
String loginPwd= scanner.nextLine();
Map<String,String> userLoginInfo =new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}
PreparedStatement (解决sql注入)
/*
1、解决SQL注入问题?
决解方法:使用户提供的信息不参与SQL语句的编译过程,问题就解决了。
要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
PreparedStatement接口继承了java.sql.Statement,是属于预编译的数据库对象,PreparedStatement原理是:预先对SQL语句的框架进行编译,然后再给sql语句传值。
2、测试结果:
用户名: fdsa
密码: fdsa' or '1'='1
登录失败
*/
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JDBCTest06 {
public static void main(String[] args) {
//初始化一个界面
Map<String,String> userLoginInfo=initUI();
//验证用户名和密码
boolean loginSuccess = login(userLoginInfo);
//输出结果
System.out.println(loginSuccess ? "登陆成功": "登录失败");
}
/**
*用户登录
* @param userLoginInfo 用户登录信息
* @return false表示失败,true表示成功
*/
private static boolean login(Map<String, String> userLoginInfo) {
//打标记的意识
boolean loginSuccess = false;
//单独定义变量
String loginName=userLoginInfo.get("loginName");
String loginPwd=userLoginInfo.get("loginPwd");
//JDBC代码
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet=null;
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2", "root", "123456");
//3、获取(预编译的)数据库对象
//sql语句的框子。其中一个?,表示一个占位符,一个2将来接收一个“值”,注意:占位符不能使用单引号括起来。
String sql="select * from t_user where login_name=? and login_password=?";
//程序执行到此处,会发送sq1语句框子给DBMS,然后DBMS进行sq1语句的预先编译。
preparedStatement = connection.prepareStatement(sql);
//给占位符?传值(第1个问号下标是1,第2个问号下标是2, JDBC中所有下标从1开始。)
preparedStatement.setString(1,loginName);
preparedStatement.setString(2,loginPwd);
//4、执行SQL
resultSet=preparedStatement.executeQuery();
//处理结果集
if(resultSet.next()){
//登录成功
loginSuccess=true;
}
//释放资源
}catch(ClassNotFoundException e){
e.printStackTrace();
}catch (SQLException e){
e.printStackTrace();
}finally {
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return loginSuccess;
}
/**
* 初始化用户界面
* @return 用户输入的用户名和密码等登录信息
*/
private static Map<String, String> initUI() {
Scanner scanner = new Scanner(System.in);
System.out.println("用户名: ");
String loginName = scanner.nextLine(); // nextLine() 读取整行数据
System.out.println("密码: ");
String loginPwd= scanner.nextLine();
Map<String,String> userLoginInfo =new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}
Statement和PreparedStatement的对比
Statement和PreparedStatement的对比
Statement存在sql注入问题,PreparedStatement解决SQL注入问题。
Statement是编译一次执行一次。PreparedStatement是编译一次,可执行N次。PreparedStatement效率较高一些。
PreparedStatement会在编译阶段做类型的安全检查。
综上,PreparedStatement使用较多。只在极少数情况需要使用Statement。
Statement的应用场景
需求: 用户在控制台输入desc就是降序,输入asc就是升序
4、Statement使用的场景
业务方面要求必须支持SQL注入的时候。: Statement支持sql注入,凡是业务方面要求是需要进行sqI语句拼接的,必须使用Statement。
例如: 在页面实现降序、升序功能的时候,需要在SQL语句的尾端使用order BY ASC 或 DESC 而此时使用PreparedStatement进行值传递,向已
编译好的SQL语句中传入’ASC’或’DESC’时,将不符合SQL语句规范,导致执行失败。 此时便需要Statement进行sql注入。
总结: SQL拼接用Statement, 往SQL语句中传值用PreparedStatement 。
/*
4、Statement使用的场景
业务方面要求必须支持SQL注入的时候。: Statement支持sql注入,凡是业务方面要求是需要进行sqI语句拼接的,必须使用Statement。
例如: 在页面实现降序、升序功能的时候,需要在SQL语句的尾端使用order BY ASC 或 DESC 而此时使用PreparedStatement进行值传递,向已
编译好的SQL语句中传入'ASC'或'DESC'时,将不符合SQL语句规范,导致执行失败。 此时便需要Statement进行sql注入。
总结: SQL拼接用Statement, 往SQL语句中传值用PreparedStatement 。
*/
import java.sql.*;
import java.util.Scanner;
/*
用户在控制台输入desc就是降序,输入asc就是升序
*/
public class JDBCTest07 {
public static void main(String[] args) {
/*
//测试结果: You have an error in your SQL syntax;
// check the manual that corresponds to your MySQL server version for the right syntax to use near ''asc'' at line 1
Scanner scanner= new Scanner(System.in);
System.out.println("请输入desc或asc,desc表示降序,asc表示升序");
System.out.print("请输入: ");
String keywords = scanner.nextLine(); //捕获输入的值
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection =DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2","root","123456");
//获取数据库预编译对象
String sql=" select * from t_user order by login_name ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,keywords);
//执行sql
resultSet = preparedStatement.executeQuery();
//处理结果集
while (resultSet.next()){
String a = resultSet.getString("id");
String b = resultSet.getString("login_name");
String c = resultSet.getString("realName");
System.out.println(a+","+b+","+c);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e){
e.printStackTrace();
}finally {
try {
if (resultSet!=null){
resultSet.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (preparedStatement!=null){
preparedStatement .close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
*/
// 测试结果: 排序成功
Scanner scanner= new Scanner(System.in);
System.out.println("请输入desc或asc,desc表示降序,asc表示升序");
System.out.print("请输入: ");
String keywords = scanner.nextLine(); //捕获输入的值
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection =DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2","root","123456");
//获取数据库对象
statement = connection.createStatement();
//执行sql
String sql=" select * from t_user order by login_name "+keywords ;
resultSet=statement.executeQuery(sql);
//处理结果集
while (resultSet.next()){
String a = resultSet.getString("id");
String b = resultSet.getString("login_name");
String c = resultSet.getString("realName");
System.out.println(a+","+b+","+c);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e){
e.printStackTrace();
}finally {
try {
if (resultSet!=null){
resultSet.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (statement!=null){
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
preparedStatement完成insert delete update
import java.sql.*;
/*
preparedStatement完成insert delete update
*/
public class JDBCTest08 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2", "root", "123456");
//3、获取预编译的数据库对象
/* 一、(插入一条记录)
String sql = " insert into t_user(id,login_name,login_password,realName) values (?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,10);
preparedStatement.setString(2,"Tom");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"汤姆");
*/
/* 二、修改一条记录
String sql = " update t_user set login_name=?,realName=? where id=? ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(3,1);
preparedStatement.setString(1,"GGbood");
preparedStatement.setString(2,"鸡鸡bong");
*/
/* 三、删除一条记录 */
String sql = " delete from t_user where id=? ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,1);
//4、执行sql
int count = preparedStatement.executeUpdate();
System.out.println(count);
}catch (SQLException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}finally {
//6、释放资源
try {
if(preparedStatement!=null){
preparedStatement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
JDBC事务机制 (自动提交,有风险)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
JDBC事务机制:
1、JDBC中的事务是自动提交的,什么是自动提交?
只要执行任意一条DM语句,则自动提交一次。这是JDBc默认的事务行为。
但是在实际的业务当中,通常都是N条DM语句共同联合才能完成的,必须保证他们这些DM语句在同一个事务中同时成功或者同时失败。
2、以下程序先来验证一下JDBc的事务是否是自动提交机制!
测试结果: JDBc中只要执行任意一条 DMI语句,就提交一次。
说明: 程序执行到断点处时,count已被赋值为1,说明第一次插入操作已经执行,
但此时查看数据库,发现数据库的数据已经被更改,说明jdbc的事务已经进行了提交,尽管后面的sql操作还没有执行( 若这次操作失败,则会出现事故 )
*/
public class JDBCTest09 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2", "root", "123456");
//3、获取预编译的数据库对象
String sql = " insert into t_user(id,login_name,login_password,realName) values (?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);
// 第一次给占位符传值
preparedStatement.setInt(1,14);
preparedStatement.setString(2,"Tom2");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"汤姆");
int count = preparedStatement.executeUpdate();
System.out.println(count);
// 重新给占位符传值
preparedStatement.setInt(1,15);
preparedStatement.setString(2,"Tom3");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"汤姆");
count = preparedStatement.executeUpdate();
System.out.println(count);
}catch (SQLException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}finally {
//6、释放资源
try {
if(preparedStatement!=null){
preparedStatement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
账户转账演示事务 (决解方法)乄
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
账户转账演示事务
sql脚本:
create table t_act ( actno int, balance double(10,2) ) ;
insert into t_act(actno,balance) values ( 111,20000 ),(222,0);
当执行完第一次sql语句后,出现空指针异常导致后面的程序无法执行,可事务已经自动提交了,所以丢了10000元。
解决方法: 要将数据库JDBC的自动提交机制改为手动。
connection.setAutoCommit(false); 将此连接的自动提交模式设置为给定状态。
connection.commit(); 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
connection.rollback(); 撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。
*/
public class JDBCTest11 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2", "root", "123456");
//将自动提交机制改为手动提交
connection.setAutoCommit(false); // setAutoCommit(): 将此连接的自动提交模式设置为给定状态。
//3、获取预编译的数据库对象
String sql=" update t_act set balance=? where actno=? ";
preparedStatement = connection.prepareStatement(sql);
//给?传值
preparedStatement.setDouble(1,10000);
preparedStatement.setInt(2,111);
int count = preparedStatement.executeUpdate();
System.out.println(count);
//中间发生空指针异常
String s= null;
s.toString();
//再次给?传值
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setDouble(1,10000);
preparedStatement.setInt(2,222);
count += preparedStatement.executeUpdate();
System.out.println(count==2 ? "转账成功" : "转账失败");
// 程序能够走到这里说明以上程序没有异常,事务结束,手动提交数据
connection.commit(); //使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
}catch (Exception e){
try {
//回滚事务
if(connection!=null){
connection.rollback();
}
}catch (SQLException exception){
exception.printStackTrace();
}
e.printStackTrace();
}finally {
//6、释放资源
try {
if(preparedStatement!=null){
preparedStatement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
JDBC工具类的封装
package utils;
import java.sql.*;
/*
JDBC工具类,简化JDBC编程
*/
public class DBUtil {
/*
工具类中的构造方法都是私有的。
因为工具类中的方法都是静态的,不需要new对象,直接采用类名调用。
*/
private DBUtil(){}
//静态代码块在类加载时执行,并且只执行一次。
/**
* 注册驱动
*/
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:13306/atguigudb2","root","123456");
}
/**
* 关闭资源
* @param connection 连接对象
* @param statement 数据库操作对象
* @param resultSet 结果集
*/
public static void close(Connection connection, Statement statement,ResultSet resultSet){
try {
if(resultSet!=null){
resultSet.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(statement!=null){
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
JDBC实现模糊查询
import utils.DBUtil;
import java.sql.*;
/*
1、测试DBUtil
2、模糊查询怎么写 (查询员工名字第二个字母是a的)
*/
public class JDBCTest12 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
//1、注册驱动
//2、获取连接
connection = DBUtil.getConnection();
//3、获取预编译数据库对象
String sql = " select login_name from t_user where login_name like ? ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"_a%");
//4、执行SQL
resultSet = preparedStatement.executeQuery();
//5、处理结果集
while (resultSet.next()){
String a = resultSet.getString("login_name");
System.out.println(a);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//6、释放资源
DBUtil.close(connection,preparedStatement,resultSet);
}
}
}
在Java应用层面演示SQL的悲观锁(for update)
for update (悲观锁or行级锁)
悲观锁: 事务必须排队执行。若A事务正在操作数据库中的一些数据,此时被操作的这些数据将被锁住,不允许被并发。只有等A事务结束了,等着的B事务才能继续(要是A一直不结果,B只能一直等着)。
乐观锁: 支持并发,事务也不需要排队,只不过需要一个版本号。
id salary name
1 7000 jack 1.1
事务1(同时操作数据库) --> 读取版本号为1.1 ->> 先一步操作完毕,提交数据,校对版本号发现一致,操作成功,版本号被修改为1.2 。
事务2(同时操作数据库) --> 读取版本号为1.1 ->> 比A事务后操作完,再校对版本号发现不一致,回滚操作。
import utils.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
此程序开启一个事务,这个事务专门进行查询,并且使用行级锁/悲观锁,锁住相关的记录。
*/
public class JDBCTest13 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement =null;
ResultSet resultSet=null;
try {
//1、注册驱动
//2、获取连接
connection = DBUtil.getConnection();
//关闭事务自动提交
connection.setAutoCommit(false);
//3、获取预定义数据库对象
String sql=" select id,login_name,realName from t_user where id=? for update ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,3);
//4、执行SQL
resultSet = preparedStatement.executeQuery();
//5、处理结果集
while (resultSet.next()){
int a=resultSet.getInt("id");
String b=resultSet.getString("login_name");
String c=resultSet.getString("realName");
System.out.println(a+","+b+","+c);
}
//提交事务
connection.commit();
}catch (SQLException e){
try {
//事务回滚
if (connection!=null){
connection.rollback();
}
}catch (SQLException e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//6、释放资源
DBUtil.close(connection,preparedStatement,resultSet);
}
}
}
import utils.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
此程序负责修改被锁定的记录。
*/
public class JDBCTest14 {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement =null;
try {
connection = DBUtil.getConnection();
connection.setAutoCommit(false);
String sql=" update t_user set login_name=? where id=? ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"喜羊羊");
preparedStatement.setInt(2,3);
int count = preparedStatement.executeUpdate();
System.out.println(count);
connection.commit();
}catch (SQLException e){
try {
if (connection!=null){
connection.rollback();
}
}catch (SQLException e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
DBUtil.close(connection,preparedStatement,null);
}
}
}
Druid(德鲁伊)数据库连接池
注意导包: druid-1.1.10.jar
/* DruidTest.java */
package LianJieCi;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class DruidTest {
private static DataSource dataSource;
static {
try {
Properties properties = new Properties();
InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
properties.load(resourceAsStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {
Connection connection = dataSource.getConnection();
return connection;
}
}
/* druid.properties */
url=jdbc:mysql://localhost:13306/test
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=10
/*JDBCUtiles.java*/
package LianJieCi;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author shkstart
* @create 2022-03-23 11:20
*/
public class JDBCUtiles {
public static void main(String[] args) throws SQLException {
DruidTest druidTest = new DruidTest();
Connection connection = druidTest.getConnection();
System.out.println(connection);
}
}
Apache-DBUtils实现CRUD操作
注意导包:commons-dbutils-1.3.jar
QueryRunnerTest.java
package dbutils;
import LianJieCi.DruidTest;
import bean.Customer;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.*;
import java.util.List;
import java.util.Map;
//commons-dbutils 是Apache组织提供的一个开源JDBC具类库,封装了针对于数据库的增删改查操作。
public class QueryRunnerTest {
@Test
//测试插入
public void testInsert() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
System.out.println(conn);
String sql=" INSERT INTO temp1(id,NAME) VALUES (?,?) ";
QueryRunner queryRunner = new QueryRunner();
int insertCount = queryRunner.update(conn,sql,6,"龙");
System.out.println("添加了"+insertCount+"条记录");
} catch (SQLException e) {
e.printStackTrace();
}finally {
//致命操作: 此处应该写在finally中
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Test
//测试查询,返回单个对象
public void testSelect1() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql="SELECT id,NAME FROM temp1 where id=?";
//BeanHandler :是ResultSetHandler接口的实现类,用于封装表中的一条记录。
BeanHandler<Customer> handler= new BeanHandler<Customer>(Customer.class);
QueryRunner queryRunner = new QueryRunner();
Customer customer = queryRunner.query(conn, sql, handler, 1);
System.out.println(customer);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//测试查询,返回多个对象
public void testSelect2() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql="SELECT id,NAME FROM temp1 where id>?";
//BeanListHandler :是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合。
BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
QueryRunner queryRunner = new QueryRunner();
List<Customer> list = queryRunner.query(conn, sql, handler, 1);
list.forEach(System.out::println);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//测试查询,MapHandler(单条)
public void testSelect3() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql="SELECT id,NAME FROM temp1 where id=?";
//MapHandler :是ResultSetHandler接口的实现类,对应表中的一条记录。将字段及相应字段的值作为map中的key和value。
MapHandler handler=new MapHandler();
QueryRunner queryRunner = new QueryRunner();
Map<String, Object> map = queryRunner.query(conn, sql, handler, 1);
System.out.println(map);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//测试查询,MapListHandler(多条)
public void testSelect4() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql="SELECT id,NAME FROM temp1 where id>?";
//MapListHandler :是ResultSetHandler接口的实现类,对应表中的多条记录。将字段及相应字段的值作为map中的key和value。将这些map添加到List中。
MapListHandler handler=new MapListHandler();
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> List = queryRunner.query(conn, sql, handler, 1);
List.forEach(System.out::println);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//测试查询,ScalarHandler,用于查询特殊字段
public void testSelect5() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql=" select count(*) from temp1 ";
ScalarHandler handler = new ScalarHandler();
QueryRunner queryRunner = new QueryRunner();
Long count= (Long) queryRunner.query(conn, sql, handler);
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//测试查询,ScalarHandler,用于查询特殊字段
public void testSelect6() {
Connection conn=null;
try {
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql=" select max(id) from temp1 ";
ScalarHandler handler = new ScalarHandler();
QueryRunner queryRunner = new QueryRunner();
int count= (int) queryRunner.query(conn, sql, handler);
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//如果以上实现类都不满足业务需求,自己自定义一个Interface ResultSetHandler<T>接口的实现类。
public void testSelect7() {
Connection conn=null;
try {
QueryRunner queryRunner = new QueryRunner();
DruidTest druidTest = new DruidTest();
conn = druidTest.getConnection();
String sql="select * from temp1 where id=?";
//自定义 (匿名接口实现类)
ResultSetHandler<Customer> handler=new ResultSetHandler<Customer>() {
@Override
public Customer handle(ResultSet resultSet) throws SQLException {
// return null;
if(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("NAME");
Customer customer = new Customer(id, name, null, null);
return customer;
}
return null;
}
};
Customer customer = queryRunner.query(conn, sql, handler, 1);
System.out.println(customer);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Test
//使用dbutils.jar中提供的DbUtils工具类,实现资源的关闭。
public static void closeResource2(Connection connection, Statement statement, ResultSet resultSet, PreparedStatement preparedStatement){
/* 一 较手写省了if
try {
DbUtils.close(preparedStatement);
} catch (SQLException e) {
e.printStackTrace();
}
try {
DbUtils.close(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
try {
DbUtils.close(statement);
} catch (SQLException e) {
e.printStackTrace();
}
try {
DbUtils.close(connection);
} catch (SQLException e) {
e.printStackTrace();
} */
/* 二 较手写省了if,try */
DbUtils.closeQuietly(preparedStatement);
DbUtils.closeQuietly(resultSet);
DbUtils.closeQuietly(statement);
DbUtils.closeQuietly(connection);
}
@Test
//关闭资源(手动写)
public static void closeResource1(Connection connection, Statement statement, ResultSet resultSet, PreparedStatement preparedStatement){
try {
if ( preparedStatement!=null ){
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if ( resultSet!=null ){
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement!=null ){
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if ( connection!=null ){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/* Customer.java */
package bean;
import java.sql.Date;
/*
* ORM编程思想 (object relational mapping)
* 一个数据表对应一个java类
* 表中的一条记录对应java类的一个对象
* 表中的一个字段对应java类的一个属性
*
*/
public class Customer {
private int id;
private String name;
private String email;
private Date birth;
public Customer() {
super();
}
public Customer(int id, String name, String email, Date birth) {
super();
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", birth=" + birth + "]";
}
}
<!-- druid.properties -->
url=jdbc:mysql://localhost:13306/dbtest12
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=10
总结
传统创建一次性连接
/* jdbc_1.java */
package utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @author shkstart
* @create 2022-03-24 14:48
*/
public class jdbc_1 {
public static void main(String[] args) {
Connection connection= null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
connection = new getConnection1().getConnection();
String sql="select * from temp1 ";
ps = connection.prepareStatement(sql);
resultSet = ps.executeQuery();
if (resultSet.next()){
String id = resultSet.getString("id");
String NAME = resultSet.getString("NAME");
System.out.println(id+","+NAME);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
close close = new close();
close.close(connection,null,ps,resultSet);
}
}
}
/* getConnection1.java */
package utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;
/**
* @author shkstart
* @create 2022-03-24 14:56
*/
public class getConnection1 {
public Connection getConnection() throws Exception{
ResourceBundle resource = ResourceBundle.getBundle("getConnection_p");
String driver = resource.getString("driver");
String url = resource.getString("url");
String user = resource.getString("user");
String password = resource.getString("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url,user,password);
return connection;
}
}
/* close.java */
package utils;
import java.sql.*;
public class close {
public void close(Connection connection, Statement statement, PreparedStatement preparedStatement, ResultSet resultSet){
try {
if(resultSet!=null){
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(preparedStatement!=null){
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(statement!=null){
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
<!-- getConnection_p.properties -->
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:13306/dbtest12
user=root
password=123456
使用数据库连接池
/* jdbc_2.java */
package utils;
// DataSource数据源
// Properties类 读取配置文件
// commons-dbutils工具类jar包
// QueryRunner类 一共有6种方法,query对应sql查询,update(SQL中INSERT,UPDATE,或DELETE语句)....
//ResultSetHandler处理结果集 8种,BeanListHandler、ArrayListHandler、ScalarHandler....
//BeanListHandler类 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中。
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class jdbc_2 {
public static void main(String[] args) {
Connection connection=null;
try {
druid_conn druid = new druid_conn();
connection = druid.getConnection();
String sql="select * from temp1";
//BeanListHandler :是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合。
BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
QueryRunner queryRunner = new QueryRunner();
List<Customer> list = queryRunner.query(connection,sql, handler);
list.forEach(System.out::println);
} catch (SQLException e) {
e.printStackTrace();
}finally {
//使用dbutils.jar中提供的DbUtils工具类,实现资源的关闭。
DbUtils.closeQuietly(connection);
}
}
}
/* druid_conn.java */
package utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author shkstart
* @create 2022-03-24 20:56
*/
public class druid_conn {
private static DataSource dataSource ;
static {
try {
InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
Properties pro=new Properties();
pro.load(resourceAsStream);
dataSource= DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException{
return dataSource.getConnection();
}
}
/* Customer.java */
package utils;
/**
* @author shkstart
* @create 2022-03-24 21:18
*/
public class Customer {
private int id;
private String name;
public Customer() { super(); }
public Customer(int id, String name) {
super();
this.id = id;
this.name = name;
}
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;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + "]";
}
}
<!-- druid.properties -->
url=jdbc:mysql://localhost:13306/dbtest12
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=10