List item
JDBC(Java DataBase Connectivity)
什么是JDBC
简单的来说就是在Java中对数据库进行增删改查等一系列操作. 想实现这些操作就要通过JDBC来搭建项目并关联数据库.
JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。
执行流程:
- 连接数据源,如:数据库。
- 为数据库传递查询和更新指令。
- 处理数据库响应并返回的结果。
JDBC 架构
分为双层架构和三层架构。
双层架构
作用:此架构中,Java Applet 或应用直接访问数据源。
条件:要求 Driver 能与访问的数据库交互。
机制:用户命令传给数据库或其他数据源,随之结果被返回。
部署:数据源可以在另一台机器上,用户通过网络连接,称为 C/S配置(可以是内联网或互联网)。
三层架构
侧架构特殊之处在于,引入中间层服务。
流程:命令和结构都会经过该层。
吸引:可以增加企业数据的访问控制,以及多种类型的更新;另外,也可简化应用的部署,并在多数情况下有性能优势。
历史趋势: 以往,因性能问题,中间层都用 C 或 C++ 编写,随着优化编译器(将 Java 字节码 转为 高效的 特定机器码)和技术的发展,如EJB,Java 开始用于中间层的开发这也让 Java 的优势突显出现出来,使用 Java 作为服务器代码语言,JDBC随之被重视。
JDBC 编程步骤
加载驱动程序
驱动程序根据不同的语言 , MySQL提供了面向不同语言的驱动程序 . 可以在MySQL官网获取 , 注意本地MySQL的版本号
选择JetBrain的IDEA作为开发工具 ,
下载完成后 , 将jar包放到Java工程目录下 , 新建lib来存放.然后右键lib文件夹 add as library...
此时就可以发现lib下的mysql是可以打开的文件夹
测试连接
新建一个.class文件
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* JDBCStudy
* changyulin
* JDBC的部署测试
**/
public class JDBCTest {
public static void main(String[] args) throws Exception {
//注册加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获得连接
String url = "jdbc:mysql://localhost:3306/company_db";
String user = "root";
String password = "cyl12580";
Connection connection = DriverManager.getConnection(url, user, password);
if (connection!=null){
System.out.println("数据库连接成功");
}else{
System.out.println("数据库连接失败");
}
}
JDBC对数据库中表进行操作
更新数据(DML)
对表的更新操作包括 增加 , 删除 , 修改
增加一条数据
package com.Study.JDBCTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* JDBCStudy
* changyulin
* JDBC的部署测试
**/
public class JDBCTest {
public static void main(String[] args) throws Exception {
//注册加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获得连接
String url = "jdbc:mysql://localhost:3306/company_db";
String user = "root";
String password = "cyl12580";
Connection connection = DriverManager.getConnection(url, user, password);
if (connection!=null){
System.out.println("数据库连接成功");
}else{
System.out.println("数据库连接失败");
}
assert connection != null;
//获得执行sql语句的对象
Statement statement = connection.createStatement();
//执行sql语句
String sql = "INSERT INTO t_jobs(JOB_ID, JOB_TITLE, MIN_SALARY, MAX_SALARY) VALUES('Java_SE','Java_Lecture',4000,10000);";
int result = statement.executeUpdate(sql);
System.out.println(result);
//释放资源
statement.close;
connection.close;
}
}
这里用result来接收返回的值 , 因为修改后会返回几行受到了影响 注意SQL语句的正确书写以及列名表名的正确书写 不熟悉的话建议现在命令行敲一下
-
注意 : 在缩写DML语句时 , 一定要注意字符串参数的符号是单引号的’值’
-
DML 语句 : 增删改时 , 返回受影响的行数
-
DQL 语句 : 查询时 , 返回结果数据(ResultSet结果集)
删除数据
//删除一行数据
String DeleteSql = "DELETE FROM t_jobs WHERE JOB_ID = 'Java_SE';";
System.out.println(statement.executeUpdate(DeleteSql));
statement.close();
connection.close();
更新数据
//更新一条数据
String UpdateSql = "UPDATE t_jobs SET MIN_SALARY = 6000 WHERE JOB_ID = 'Java_SE';";
System.out.println(statement.executeUpdate(DeleteSql));
statement.close();
connection.close();
释放资源
先开后关的原则
- 先释放statemen
- 再释放connection
查询数据(DQL)
ResultSET结果集
在执行查询SQL之后 , 存放查询到的结果数据集
接收结果集
ResultSet rs = statement.executeQuery(sql)
遍历ResultSet中的数据
ResultSet以表(table)结构进行存储 , 需要通过JDBC API 将其中数据进行依次获取
- 数据行指针 : 初始位置在第一行数据前 , 每调用一次 boolean next() 方法 ResultSet的指针向下移动一行 , 结果为true , 表示当前行有数据
- rs.getXxx(整数) : 代表根据列的编号顺序获得 , 从1开始
- rs.getXxx(“列名”) : 代表根据列名获得
boolean next() throws SQLException //判断 resultset 结果集中下一行是否存在数据
package com.Study.JDBCTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* JDBCStudy
* changyulin
* JDBC的部署测试
**/
public class JDBCTest {
public static void main(String[] args) throws Exception {
//注册加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获得连接
String url = "jdbc:mysql://localhost:3306/company_db";
String user = "root";
String password = "cyl12580";
Connection connection = DriverManager.getConnection(url, user, password);
if (connection != null) {
System.out.println("数据库连接成功");
} else {
System.out.println("数据库连接失败");
}
assert connection != null;
//获得执行sql语句的对象
Statement statement = connection.createStatement();
//查询一张表
String SearchSQL = "SELECT * FROM t_jobs ";
ResultSet resultSet = statement.executeQuery(SearchSQL);
//逐行遍历结果集中的数据
while (resultSet.next()) {
String s1 = resultSet.getString(1);
String s2 = resultSet.getString(2);
String s3 = resultSet.getString(3);
String s4 = resultSet.getString(4);
System.out.println(s1 + '/' + s2 + '/' + s3 + '/' + s4);
}
//释放资源
resultSet.close();
statement.close();
connection.close();
}
}
常见错误
- 找不到类
- SQL语句错误 (最好现在客户端工具中测试一下SQL语句)
- String值没加单引号
- 主键值已存在或混乱 , 更改主键值或清空表
综合案例 : 实现登录
创建表
用户编号 int 自动生成 不能重复 不能为空
用户名 varchar(20) 不能为空 不能重复
密码 varchar(8) 不能为空
手机号码 int(11) 不能重复 不能为空
SHOW DATABASES;
CREATE database UserLogin;
use UserLogin;
create table User
(
UserNo int primary key auto_increment,
UserName varchar(10) unique not null,
Password varchar(8) not null,
PhoneNum varchar(11) unique not null
) char set utf8;
insert into User(username, password, phonenum)
VALUES ('Cenarius0', '12580', '17633659080');
insert into User(username, password, phonenum)
VALUES ('Cenarius1', '12581', '17633659081');
insert into User(username, password, phonenum)
VALUES ('Cenarius2', '12582', '17633659082');
insert into User(username, password, phonenum)
VALUES ('Cenarius3', '12583', '17633659083');
insert into User(username, password, phonenum)
VALUES ('Cenarius4', '12584', '17633659084');
登录功能实现
package com.Study.JDBCTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
/**
* JDBCStudy
* changyulin
* 用户登录功能的实现
**/
public class UserLogin {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String UserName = input.next();
System.out.println("请输入密码");
String Password = input.next();
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/UserLogin", "root", "cyl12580");
assert connection != null;
//创建SQL语句接收
Statement statement = connection.createStatement();
String SearchUserInfo = "select * from UserLogin.User where UserName = '" + UserName + "'";
ResultSet resultSet = statement.executeQuery(SearchUserInfo);
//先判断是否查询到
if (resultSet.next()) {
//判断密码是否正确
if (Password.equals(resultSet.getString("Password"))) {
System.out.println("登录成功");
} else {
System.out.println("密码错误");
}
} else {
//未查询到数据则代表用户不存在
System.out.println("用户不存在");
}
//释放资源
resultSet.close();
statement.close();
connection.close();
}
}
PreparedStatement
SQL注入问题
回到上边登录的问题 , 假如我们输入
abc'or 1=1;#
,密码随便输入. 那么永远登陆成功因为此时sql语句已经发生了改变
SQL注入问题的原因
用户输入数据中有SQL语句关键字 , 导致SQL语句发生了变化 , 导致返回结果一直为TRUE
SQL注入问题的解决
由于编写的SQL语句是在用户输入数据整合后再进行编译 , 所以为了避免SQL注入问题 , 我们要使SQL语句在用户输入数据前就已经进行编译完整的SQL , 再进行数据填充
PreparedStatement的应用
PreparedStatement继承了Statement的接口 , 所以执行SQL语句的方法无异
- 预编译SQL语句 , 执行效率高
- 安全 , 避免SQL注入
- 可以动态填充数据 , 执行多个重构的SQL语句
- 参数标记以及动态参数绑定
package com.Study.JDBCTest;
import java.sql.*;
import java.util.Scanner;
/**
* JDBCStudy
* changyulin
* PreparedStatementTest
**/
public class UserLogin2 {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String UserName = input.next();
System.out.println("请输入密码");
String Password = input.next();
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/UserLogin", "root", "cyl12580");
//预编译SQL语句
String SearchUserInfo = "select * from UserLogin.User where UserName = ?";
PreparedStatement preparedStatement = connection.prepareStatement(SearchUserInfo);
//定义占位符内容
preparedStatement.setString(1, UserName);
//执行查询
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
if (Password.equals(resultSet.getString("Password"))) {
System.out.println("登录成功");
} else {
System.out.println("密码错误");
}
} else {
System.out.println("用户不存在");
}
//释放资源
resultSet.close();
preparedStatement.close();
connection.close();
}
}
封装工具类
- 在实际的JDBC的使用中 , 存在这大量的重复代码. 例如连接数据库 , 关闭数据库等
- 我们需要把传统的JDBC代码进行重构 , 抽取出通用的JDBC工具类
工具类的核心思想
将固定性的代码进行封装
DBUtils{
public static Connection getConnection(){
//1.加载驱动
//2.获取连接对象
//3.返回连接对象
}
//关闭资源
public static void closeAll(Connection con , Statement sta , ResultSet rs){
rs.close;
sta.close;
con.close;
}
}
重用性方案
- 封装获取连接 , 释放资源两个方法
我们先来写一个工具类
package com.Study.JDBCUtils;
import java.sql.*;
/**
* JDBCStudy
* changyulin
* 封装JDBC连接释放工具类
**/
public class JDBCUtils {
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/UserLogin", "root", "cyl12580");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void CloseAll(Connection con, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
然后我们来改动一下上边的代码
package com.Study.JDBCTest;
import com.Study.JDBCUtils.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
/**
* JDBCStudy
* changyulin
* PreparedStatementTest
**/
public class UserLogin2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String UserName = input.next();
System.out.println("请输入密码");
String Password = input.next();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载驱动
connection = JDBCUtils.getConnection();
//预编译SQL语句
String SearchUserInfo = "select * from UserLogin.User where UserName = ?";
preparedStatement = connection.prepareStatement(SearchUserInfo);
//定义占位符内容
preparedStatement.setString(1, UserName);
//执行查询
resultSet = preparedStatement.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
try {
assert resultSet != null;
if (resultSet.next()) {
if (Password.equals(resultSet.getString("Password"))) {
System.out.println("登录成功");
} else {
System.out.println("密码错误");
}
} else {
System.out.println("用户不存在");
}
} catch (SQLException e) {
e.printStackTrace();
}
//释放资源
JDBCUtils.CloseAll(connection, preparedStatement, resultSet);
}
}
这里来说一个点 , 因为我们工具类中有类加载 , 那么是否每次在运行这个工具类的时候都会做一次类加载呢?
显然是不会的 , 因为在Java类加载的时候它会进行判断 , 加载的类是否存在 , 如果存在在不加载
所以不妨再将工具类改进一下 , 我们将类加载放到静态代码块中 , 默认运行一次
静态代码块在类加载时被执行,且只执行一次。
package com.Study.JDBCUtils;
import java.sql.*;
/**
* JDBCStudy
* changyulin
* 封装JDBC连接释放工具类
**/
public class JDBCUtils {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/UserLogin", "root", "cyl12580");
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void CloseAll(Connection con, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
跨平台方案
- 定义public static final Properties prop = new Properties(); //读取配置文件的Map
- 定义一个静态代码块
static{ //首次使用工具时加载驱动 //通过复用本类自带流,读取jdbc.properties配置文件 classPath=bin InputStream is = JDBCUtils.class.getResourceAsStream("路径"); prop.loda(is); //通过driverName的键获取对应的值 String driverName = prop.getProperty("driver"); //加载驱动 Class.forName(driverName); }
这样做的主要目的是假如我们修改了使用的数据库或者说修改了用户名密码等 , 不需要去修改代码. 只需要去修改配置文件中的信息即可
首先我们在src目录下新建一个.properties文件存放信息
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/UserLogin
user=root
password=*********
接着我们改动一下上边的代码 , 已输入流的形式来读取.properties中的信息
package com.Study.JDBCUtils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JDBCStudy
* changyulin
* 封装JDBC连接释放工具类
**/
public class JDBCUtils {
public static final Properties prop = new Properties();
//静态代码块
static {
//读取配置文件
InputStream inputStream = JDBCUtils.class.getResourceAsStream("/db.properties");
try {
//加载配置文件到流
prop.load(inputStream);
//加载类
Class.forName(prop.getProperty("driver"));
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("user"), prop.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void CloseAll(Connection con, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
之后的话 , 如果我们要改动数据库或者一些登录信息之类的 . 只需要改动.properties文件中信息即可
ORM
ORM(Object Relational Mapping)
从数据库查询到的结果(ResultSet)在进行遍历时 , 逐行遍历 , 取出的都是零散的数据 . 但是在实际应用开发中 , 我们需要将零散的数据进行封装处理
实体类(entity): 零散数据的载体
- 一行数据中 , 多个零散的数据进行处理
- 通过entity的规则对表中的数据进行封装
- 表名=类名; 列名=属性名; 提供各个属性的get set方法
- 提供无参构造方法
ORM应用
首先我们先创建一个List容器来存放我们查询的数据 , 按照表名=类名 列名=属性名的规则先创建一个类
package com.Study;
/**
* JDBCStudy
* changyulin
* 封装实体类
* 类名=表名 属性名=列名
**/
public class T_jobs {
private String job_id;
private String job_title;
private String min_salary;
private String max_salary;
public String getJob_id() {
return job_id;
}
public void setJob_id(String job_id) {
this.job_id = job_id;
}
public String getJob_title() {
return job_title;
}
public void setJob_title(String job_title) {
this.job_title = job_title;
}
public String getMin_salary() {
return min_salary;
}
public void setMin_salary(String min_salary) {
this.min_salary = min_salary;
}
public String getMax_salary() {
return max_salary;
}
public void setMax_salary(String max_salary) {
this.max_salary = max_salary;
}
@Override
public String toString() {
return "T_jobs{" +
"job_id='" + job_id + '\'' +
", job_title='" + job_title + '\'' +
", min_salary='" + min_salary + '\'' +
", max_salary='" + max_salary + '\'' +
'}';
}
}
然后跟之前一样 , 我们来遍历T_JOBS这张表 , 并将遍历的结果放入对象中 , 并且将对象存到List里
package com.Study;
import com.Study.JDBCUtils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* JDBCStudy
* changyulin
**/
public class ORMTest {
public static void main(String[] args) {
Connection connection = JDBCUtils.getConnection();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
List<T_jobs> job_list = new ArrayList<>();
try {
preparedStatement = connection.prepareStatement("select * from company_db.t_jobs;");
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String job_id = resultSet.getString(1);
String job_title = resultSet.getString(2);
String min_salary = resultSet.getString(3);
String max_salary = resultSet.getString(4);
//将数据存入到对象中
T_jobs t_jobs = new T_jobs();
t_jobs.setJob_id(job_id);
t_jobs.setJob_title(job_title);
t_jobs.setMax_salary(max_salary);
t_jobs.setMin_salary(min_salary);
//将对象加载到list里
job_list.add(t_jobs);
}
for (T_jobs t : job_list) {
System.out.println(t);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseAll(connection, preparedStatement, resultSet);
}
}
}
DAO数据访问对象 (Data Acces Object)
- DAO实现了业务逻辑与数据库访问相分离
- 对同一张表的所有操作封装在XxxDaoImpl对象中
- 根据增删改查的不同功能实现具体的方法 (insert update delete select selectAll)
其实就可以简单的理解为DAO是介于数据库和程序之间的中间对象 , 为两者提供服务
创建数据库
- 县创建一个新的数据库以及表供我们等下使用
- id int 主键 自动增长
- name varchar(20) 非空
- age int 非空
- bornDate date
- email varchar(20)
- address varchar(20)
CREATE DATABASE PERSON_DB;
use PERSON_DB;
create table person
(
id int primary key auto_increment,
name varchar(20) not null,
age int not null,
bornDate date,
email varchar(20),
address varchar(20)
) charset = utf8;
封装实体类
这个没什么好说的,其实就是创建一个你需要操作的类对象.
封装工具类
这点也和上边一样,把一些重复的代码操作,比如获取连接,声明PreparedStatement这些的重复代码封装起来,同样的关闭所有连接我们也可以封装起来.
封装操作类
紧接着我们对数据库应该有很多基本的操作 , 也就是增删改查 . 很多事务也都是由这些操作组成的 . 所以我们完全可以把这些操作封装起来 , 提高代码复用性 ,.
package com.study;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* test
* changyulin
**/
public class PersonDAOImpl {
//对表的增加操作
public int Insert(Person person) {
if (person.getEmail() == null) {
return 0;
}
int result = 0;
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "insert into PERSON_DB.person(name,age,borndate,email,address) values(?,?,?,?,?);";
try {
connection = JDBCUtils.GetConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, person.getName());
preparedStatement.setInt(2, person.getAge());
preparedStatement.setDate(3, person.getBornDate());
preparedStatement.setString(4, person.getEmail());
preparedStatement.setString(5, person.getAddress());
result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseAll(connection, preparedStatement, null);
}
return result;
}
//对表的删除操作
public int Delete(int id) {
int result = 0;
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "delete from PERSON_DB.person where id = ?";
try {
connection = JDBCUtils.GetConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, id);
result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseAll(connection, preparedStatement, null);
}
return result;
}
//对表的修改操作
public int Update(Person person) {
Connection connection;
PreparedStatement preparedStatement;
String sql = "update PERSON_DB.person set name = ?,age = ?,bornDate = ?,email = ?,address = ? where id = ?";
int result = 0;
try {
connection = JDBCUtils.GetConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, person.getName());
preparedStatement.setInt(2, person.getAge());
preparedStatement.setDate(3, person.getBornDate());
preparedStatement.setString(4, person.getEmail());
preparedStatement.setString(5, person.getAddress());
preparedStatement.setInt(6, person.getId());
result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
//对表的查询操作
//查单个
public Person Select(int id) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Person person = new Person();
String sqlById = "select * from PERSON_DB.person where id = ?";
try {
connection = JDBCUtils.GetConnection();
preparedStatement = connection.prepareStatement(sqlById);
preparedStatement.setInt(1, id);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
person.setId(resultSet.getInt("id"));
person.setName(resultSet.getString("name"));
person.setAge(resultSet.getInt("age"));
person.setBornDate(resultSet.getDate("bornDate"));
person.setEmail(resultSet.getString("email"));
person.setAddress(resultSet.getString("address"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseAll(connection, preparedStatement, resultSet);
}
return person;
}
//查全部
public List<Person> SelectAll() {
Connection connection;
PreparedStatement preparedStatement;
ResultSet resultSet;
List<Person> personList = new ArrayList<>();
try {
connection = JDBCUtils.GetConnection();
preparedStatement = connection.prepareStatement("select * from PERSON_DB.person");
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
personList.add(new Person(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3), resultSet.getDate(4), resultSet.getString(5), resultSet.getString(6)));
}
} catch (SQLException e) {
e.printStackTrace();
}
return personList;
}
}
以上就是对数据库的增删改查的基本操作.
封装具体事务
那么这里有一个问题 , 假如我现在是一个银行管理系统 . 基础的事务比如有转账 , 存款 , 取款等等. 但是这些事务都是由很多上边所描述的基础操作组合完成的. 就比如转帐 . 我们需要先查询用户是否存在 , 密码是否正确 , 转账金额是否小于等于账户余额. 接着查询转账用户是否存在 , 存在的话 , 我们先从转账账户扣钱(一定是先扣钱) , 也就是对数据的更新操作 , 然后再对接收账户加钱 , 也是更新操作. 在面临这种问题的时候我们不可能每次都写一组基础操作 , 所以就需要把这些事物封装起来 .
转钱难免就涉及到事物的提交和回滚
学习数据库的时候应该学习过 , 在转账的过程中 , 假如我们不对事务加以控制 , 就会出现对不上账的问题. 所以要对事务加锁 , 也就是提交事务.
当然还有一种方法 , 我们在调用事务方法的时候传入一个Connection形参进去 , 来保证所有的事务的操作都在一个Connection下 , 但是这样做并不能满足代码的多态性 , 所以并不可取 . 这里我们需要借助一个学习过的方法
**ThreadLocal **
没错 , 就是Java的线程 , 我们只需要在创建线程的时候 , 判断Connection是否为空(从线程里getConnection) , 如果当前Connection为空我们就建立 连接并且将创建的连接传入ThreadLocal中去 , 每次需要创建的时候我们都从ThreadLocal中获取Connection , 这样就可以保证事务中所用的方法的Connection都是同一个Connection , 而做法也很简单 我们只需要在上边的封装工具类里加上几行代码就可以
private static ThreadLocal<Connection> threadlocal = new ThreadLocal<>();
Connection connection = threadlocal.get();
if(connetion == null){
//按照原来的创建Connection
connection = DriverManager.getConnection(prop.getProperty("url"),prop.getProperty("user"),prop.getProperty("password"));
//把创建的Connection传入ThreadLocal中
threadlocal.set(connection)
}
在具体事务中我们需要这样来提交事务
//首先关闭自动提交
connection.setAutoCommit(false);
//其实这些操作完全可以封装起来
//比如commit rollback 记得最后还是要关闭资源
一个小点 转换sql和util之间的Date类
这个其实没什么 , 就是格式转换而已 . 因为Java和MySQL所使用的Date类不一样 , 我们要把转换的方法封装起来作为一个工具类.
三层架构
什么三层架构
其实架构理解起来很简单 , 就好像每个人负责着不同的职责 . 这里的JDBC三层架构就好像每个功能的负责人
-
表示层
命名:XXXXView
收集用户的数据和需求 , 展示数据
-
业务逻辑层
命名:XXXXServiceImpl
数据加工处理 , 调用DAO完成业务实现 控制事务
-
数据访问层
命名:XXXXDaoImpl
向业务层提供数据 , 并将业务层加工好的数据返回给数据库
那其实这么一看就很明了 , 表示层更像是直接与客户沟通 , 但是对于内部逻辑他并不清楚 . 业务逻辑层对表示层负责 , 将结果传递给表示层 , 但是它并不与数据库直接交互 , 相当于数据库对于他来说是透明的 . 而数据访问层就是直接和数据库打交道 , 存取数据 , 负责与数据库的交互.
这里其实有一个很严重的问题 , 之前的所有代码 , 所有的方法操作我们都封装在了类里. 但是假如有一天我们需要对代码进行修改优化 , 比如我们对Dao进行了修改 , 可能更换了方法名 , 那岂不是需要从头到尾修改一遍 . 这显然不符合面向对象的编程思想 . 而这些操作只是提供了某些方法 , 所以我们完全可以使用接口来替代 , 后续我们只需要继承接口就可以 , 修改代码也只需要修改名字 .
搭建三层架构项目
那么从头到尾来对这个项目实现一遍.
新建一个空项目,跟之前一样的步骤,导包然后创建properties文件提供连接信息 重复一下
目录创建
需要注意的是 , 文件的结构目录
根据三层架构目录搭建应该是这样
首先src目录下创建com.person文件夹
分别创建 entity utils dao service main(view)
在entity下创建实体类Person
在utils下创建DBUtils和DateUtils
在dao下创建Persondao接口和impl文件夹 并在impl文件夹下创建PersonDaoImpl类
在service下创建PersonService接口和impl文件夹 并在impl文件夹下创建PersonServiceImpl类
上边两步非常关键 , 也就是之前说的我们将方法名写到接口里 , 后续的impl类只需要继承接口并重接方法行 , 即使修改了方法也不会出现需要疯狂改类名的情况
在main(view)下创建PersonTestDemo类
在这里我们对代码进行测试和操作
Utils搭建
- DateUtils
package com.person.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* PersonManagerSystem
* changyulin
* 时间格式转换
**/
public class DateUtils {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
//字符串转util.date
public static java.util.Date StrToUtilDate(String date) {
try {
return SIMPLE_DATE_FORMAT.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
//util.date转sql.date
public static java.sql.Date toSqlDate(java.util.Date date) {
return new java.sql.Date(date.getTime());
}
//util.date转字符串
public static String UtilDateToStr(java.util.Date date) {
return SIMPLE_DATE_FORMAT.format(date);
}
}
- DBUtils
package com.person.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* PersonManagerSystem
* changyulin
* 数据库连接
* 事务控制
* 释放资源
**/
public class DBUtils {
private static final Properties PROPERTIES = new Properties();
public static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
//静态代码块加载并读取properties文件
static {
InputStream inputStream = DBUtils.class.getResourceAsStream("/db.properties");
try {
PROPERTIES.load(inputStream);
Class.forName(PROPERTIES.getProperty("driver"));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接方法
public static Connection getConnection() {
Connection connection = threadLocal.get();
try {
if (connection == null) {
connection = DriverManager.getConnection(PROPERTIES.getProperty("url"), PROPERTIES.getProperty("user"), PROPERTIES.getProperty("password"));
threadLocal.set(connection);
}
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//开启事务方法
public static void Begin() {
Connection connection = null;
try {
connection = getConnection();
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
//提交事务方法
public static void Commit() {
Connection connection = null;
connection = getConnection();
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
//回滚事务
public static void Rollback() {
Connection connection = null;
connection = getConnection();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
//关闭资源
public static void CloseAll(Connection connection, Statement Statement, ResultSet resultSet) {
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();
threadLocal.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost::3306/companydb?useUnicode=true&characterEncoding=utf8
username=root
password=********
4.DaoUtils(见Dao层第三部分)
Dao层
- dao接口
package com.person.dao;
import com.person.entity.Person;
import java.util.List;
/**
* PersonManagerSystem
* changyulin
**/
public interface PersonDao {
public int insert(Person person);
public int update(Person person);
public int delete(Person person);
public Person select(int id);
public List<Person> selectAll();
}
- daoimpl
public class PersonDaoImpl implements PersonDao {
@Override
public int insert(Person person) {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "insert into PERSON_DB.PersonTable (Name, Age, BornDate, Email, Address) VALUES (?,?,?,?,?)";
connection = DBUtils.getConnection();
try {
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,person.getName());
preparedStatement.setInt(2,person.getAge());
preparedStatement.setDate(3, DateUtils.toSqlDate(person.getBornDate()));
preparedStatement.setString(4,person.getEmail());
preparedStatement.setString(5,person.getAddress());
int result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.CloseAll(null,preparedStatement,null);
}
return 0;
}
}
写完第一个插入方法后 , 有一个问题 . 后续的方法有很多语句都是重复的 . 比如所有的操作都要获取连接 , 然后通过PreparedStatement解析sql语句 , 显然重复的代码并不是合理的 . 所以不妨我们在Utils中假如一个新的工具类来解决这些冗余的代码 .
解决之前有个问题需要解决 , 那就是每次传入的占位符的个数并不相同 , 也就是动态的 , 并且每个占位符的数据类型也不相同 . 我们可以通过可变长参数列表来解决这个问题 .
我们只需要向方法中传入sql语句以及占位符的信息数组即可
当然查询方法也是相同的道理
- 在Utils中加入工具类
package com.person.utils;
import com.person.entity.Person;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* PersonManagerSystem
* changyulin
* 封装DaoImpl中冗余的代码
**/
public class DaoUtils {
/**
* 增删改中冗余的代码
*
* @param sql sql语句
* @param args 可变长参数列表
* @return 返回受影响的行数
*/
public static int CommonsUpdate(String sql, Object... args) {
Connection connection;
PreparedStatement preparedStatement = null;
int result;
try {
//解析sql语句
connection = DBUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
//赋值给占位符
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
return result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.CloseAll(null, preparedStatement, null);
}
return 0;
}
public static List<Person> CommonSelect(String sql, int... args) {
ResultSet resultSet;
Connection connection;
PreparedStatement preparedStatement;
List<Person> list = new ArrayList<>();
try {
connection = DBUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
list.add(new Person(resultSet.getInt(1),
resultSet.getString(2),
resultSet.getInt(3),
DateUtils.StrToUtilDate(resultSet.getDate(4).toString()),
resultSet.getString(5),
resultSet.getString(6)));
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
接着完善一下DaoImpl的代码
package com.person.dao.impl;
import com.person.dao.PersonDao;
import com.person.entity.Person;
import com.person.utils.DaoUtils;
import com.person.utils.DateUtils;
import java.util.List;
/**
* PersonManagerSystem
* changyulin
**/
public class PersonDaoImpl implements PersonDao {
@Override
public int insert(Person person) {
//language=MySQL
String sql = "insert into PERSON_DB.PersonTable (Name,Age,BornDate,Email,Address) values (?,?,?,?,?)";
Object[] args = {person.getName(), person.getAge(), DateUtils.toSqlDate(person.getBornDate()), person.getEmail(), person.getAddress()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public int update(Person person) {
//language=MySQL
String sql = "update PERSON_DB.PersonTable set Name=?,Age=?,BornDate=?,Email=?,Address=? where Id = ?";
Object[] args = {person.getName(), person.getAge(), DateUtils.toSqlDate(person.getBornDate()), person.getEmail(), person.getAddress(), person.getId()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public int delete(Person person) {
//language=MySQL
String sql = "delete from PERSON_DB.PersonTable where Id = ?";
Object[] args = {person.getId()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public Person select(int id) {
//language=MySQL
String sql = "select * from PersonTable where Id = ?";
List<Person> list = DaoUtils.CommonSelect(sql, id);
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
@Override
public List<Person> selectAll() {
//language=MySQL
String sql = "select * from PersonTable";
int[] args = new int[0];
return DaoUtils.CommonSelect(sql, args);
}
}
但是上边的代码有一个问题 , 作为工具类 , 复用性很差 . 如果换一个对象来调用 , 则这些代码就不能用了 , 所以需要想办法改变一下策略. 所以用泛型来优化一下. 并且采用回调的方式来对ORM进行封装.
先对ORM封装写一个接口和实现类
package com.person.advanced;
import java.sql.ResultSet;
/**
* PersonManagerSystem
* changyulin
* 约束封装对象的ORM
**/
public interface RowMapper<T> {
T getRow(ResultSet resultSet);
}
package com.person.advanced.impl;
import com.person.advanced.RowMapper;
import com.person.entity.Person;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* PersonManagerSystem
* changyulin
* ORM封装
**/
public class RowMapperImpl implements RowMapper<Person> {
@Override
public Person getRow(ResultSet resultSet) {
try {
if (resultSet.next()) {
return new Person(
resultSet.getInt(1),
resultSet.getString(2),
resultSet.getInt(3),
resultSet.getDate(4),
resultSet.getString(5),
resultSet.getString(6)
);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
改动一下DaoUtils里的公共查询代码
package com.person.utils;
import com.person.advanced.RowMapper;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* PersonManagerSystem
* changyulin
* 封装DaoImpl中冗余的代码
**/
public class DaoUtils<T> {
/**
* 增删改中冗余的代码
*
* @param sql sql语句
* @param args 可变长参数列表
* @return 返回受影响的行数
*/
public static int CommonsUpdate(String sql, Object... args) {
Connection connection;
PreparedStatement preparedStatement = null;
try {
//解析sql语句
connection = DBUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
//赋值给占位符
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
return preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.CloseAll(null, preparedStatement, null);
}
return 0;
}
/**
* @param sql sql语句
* @param args 可变长参数列表,查询根据
* @return 返回查询结果List
*/
public List<T> CommonSelect(String sql, RowMapper<T> rowMapper, Object... args) {
ResultSet resultSet;
Connection connection;
PreparedStatement preparedStatement;
List<T> list = new ArrayList<>();
try {
connection = DBUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
if (args != null) {
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
}
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
//回调
T t = rowMapper.getRow(resultSet);
list.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
因为引用了泛型 , 需要修改一下DaoUtilsImpl里的代码
package com.person.dao.impl;
import com.person.advanced.impl.RowMapperImpl;
import com.person.dao.PersonDao;
import com.person.entity.Person;
import com.person.utils.DaoUtils;
import com.person.utils.DateUtils;
import java.util.List;
/**
* PersonManagerSystem
* changyulin
**/
public class PersonDaoImpl implements PersonDao {
private final DaoUtils<Person> daoUtils = new DaoUtils<>();
@Override
public int insert(Person person) {
/* language=MySQL */
String sql = "insert into PERSON_DB.PersonTable (Name,Age,BornDate,Email,Address) values (?,?,?,?,?)";
Object[] args = {person.getName(), person.getAge(), DateUtils.toSqlDate(person.getBornDate()), person.getEmail(), person.getAddress()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public int update(Person person) {
/* language=MySQL */
String sql = "update PERSON_DB.PersonTable set Name=?,Age=?,BornDate=?,Email=?,Address=? where Id = ?";
Object[] args = {person.getName(), person.getAge(), DateUtils.toSqlDate(person.getBornDate()), person.getEmail(), person.getAddress(), person.getId()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public int delete(Person person) {
/* language=MySQL */
String sql = "delete from PERSON_DB.PersonTable where Id = ?";
Object[] args = {person.getId()};
return DaoUtils.CommonsUpdate(sql, args);
}
@Override
public Person select(int id) {
/* language=MySQL */
String sql = "select * from PersonTable where Id = ?";
List<Person> list = daoUtils.CommonSelect(sql, new RowMapperImpl(), id);
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
@Override
public List<Person> selectAll() {
/* language=MySQL */
String sql = "select * from PersonTable";
return daoUtils.CommonSelect(sql, new RowMapperImpl(), (Object) null);
}
}
View层
其实也就是main层 , 你做测试的地方 . 比如试一下你的功能是否能正常运行.(学习阶段嘛 , 是这样的)
Service层
这一层的主要目的就是编写一些事务 , 并且这些事务都由Dao层的基本操作完成
这个就不多讲了 , 比如银行转账流程 . 一个道理
Druid连接池
在程序初始化时 , 预先创建指定数量的数据库连接对象存在池中 , 当需要数据库时 , 从连接池中取出现有连接 , 使用完毕后放回 , 不进行关闭. 实现复用 , 节省资源
Druid连接池使用步骤
- 创建database.properties配置文件
- 引入druid-1.1.5.jar文件
配置文件
#连接设置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost::3306/companydb?useUnicode=true&characterEncoding=utf8
username=root
password=********
#初始化连接个数
initialSize=10
#最大连接个数
maxActive=50
#最小空闲个数
minIdle=5
#最长等待时间
maxWait=5000
导包
跟之前一样的步骤 , MySQL的jar包 , Druid的jar包 , Apache common dbutils的jar包
DbUtils
package com.finals.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* DruidStudyDemo
* changyulin
**/
public class DbUtils {
private static DruidDataSource druidDataSource;
static {
Properties properties = new Properties();
InputStream inputStream = DbUtils.class.getResourceAsStream("/database.properties");
try {
properties.load(inputStream);
//创建连接池
druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
test测试类
package com.finals.test;
import com.finals.utils.DbUtils;
import java.sql.Connection;
import java.sql.SQLException;
/**
* DruidStudyDemo
* changyulin
**/
public class TestPool {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
Connection connection = DbUtils.getConnection();
System.out.println(connection);
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
上边的close方法并没有关闭连接 , 而是放回了池中
Apache的DBUtils
一个由Apache组织提供的一个开源工具类库 , 简化jdbc开发步骤
主要包含的方法
- ResultSetHandler接口 :
- BeanHandler实现类 : 把一条记录转化为对象
- BeanListHandler实现类 : 把多条记录转化为list集合
- scalarHandler实现类 : 适合获取一行一列的数据
- QueryRunner : 执行sql语句的类
- 增删改 update
- 查询 Query
使用步骤
- 导入jar包
- MySQL jar包
- Druid jar包 druid-1.1.5.jar
- commons-dbutils-1.6.jar
这个没啥说的 就是简化了操作 让你觉得之前白学
- dao
package com.finals.dao;
import com.finals.entity.User;
import java.util.List;
/**
* DruidStudyDemo
* changyulin
**/
public interface UserDao {
int insert(User user);
int delete(User user);
int update(User user);
User select(String id);
List<User> selectAll();
}
package com.finals.dao.impl;
import com.finals.dao.UserDao;
import com.finals.entity.User;
import com.finals.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
/**
* DruidStudyDemo
* changyulin
**/
public class UserDaoImpl implements UserDao {
private final QueryRunner queryRunner = new QueryRunner(DbUtils.getDataSource());
@Override
public int insert(User user) {
Object[] prams = {user.getJob_id(), user.getJob_title(), user.getMin_salary(), user.getMax_salary()};
int result = 0;
try {
result = queryRunner.update("insert into company_db.t_jobs (JOB_ID, JOB_TITLE, MIN_SALARY, MAX_SALARY) VALUES (?,?,?,?)", prams);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
@Override
public int delete(User user) {
Object[] prams = {user.getJob_id()};
int result = 0;
try {
result = queryRunner.update("delete from company_db.t_jobs where JOB_ID = ? ", prams);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
@Override
public int update(User user) {
Object[] prams = {user.getJob_title(), user.getMin_salary(), user.getMax_salary()};
int result = 0;
try {
result = queryRunner.update("update company_db.t_jobs set JOB_TITLE=?,MIN_SALARY=?,MAX_SALARY=? where JOB_ID = ?");
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
@Override
public User select(String id) {
Object[] prams = {id};
try {
return queryRunner.query("select * from company_db.t_jobs where JOB_ID=?", new BeanHandler<User>(User.class), prams);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<User> selectAll() {
try {
return queryRunner.query("select * from company_db.t_jobs", new BeanListHandler<User>(User.class));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
- utils
package com.finals.utils;
import com.alibaba.druid.pool.DruidDataSource;
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;
/**
* DruidStudyDemo
* changyulin
**/
public class DbUtils {
private static DruidDataSource druidDataSource;
static {
Properties properties = new Properties();
InputStream inputStream = DbUtils.class.getResourceAsStream("/database.properties");
try {
properties.load(inputStream);
//创建连接池
druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static DataSource getDataSource(){
return druidDataSource;
}
}
entity
package com.finals.entity;
/**
* DruidStudyDemo
* changyulin
* Job实现类
**/
public class User {
private String job_id;
private String job_title;
private String min_salary;
private String max_salary;
public String getJob_id() {
return job_id;
}
public void setJob_id(String job_id) {
this.job_id = job_id;
}
public String getJob_title() {
return job_title;
}
public void setJob_title(String job_title) {
this.job_title = job_title;
}
public String getMin_salary() {
return min_salary;
}
public void setMin_salary(String min_salary) {
this.min_salary = min_salary;
}
public String getMax_salary() {
return max_salary;
}
public void setMax_salary(String max_salary) {
this.max_salary = max_salary;
}
public User() {
}
public User(String job_id, String job_title, String min_salary, String max_salary) {
this.job_id = job_id;
this.job_title = job_title;
this.min_salary = min_salary;
this.max_salary = max_salary;
}
@Override
public String toString() {
return "User{" +
"job_id=" + job_id +
", job_title='" + job_title + '\'' +
", min_salary=" + min_salary +
", max_salary=" + max_salary +
'}';
}
}