java database connectivity
JDBC:定义了一套操作所有关系型数据库的规则(接口)。各个数据库厂商去实现这套接口,提供数据库驱动jar包,我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
步骤
1、导入驱动jar包
2、注册驱动
3、获取数据库连接对象Connection
4、定义sql
5、获取执行sql语句的对象
6、执行sql,接受返回结果
7、处理结果
8、释放资源
public class jdbcDemo01 {
public static void main(String[] args) throws Exception {
//1、导入驱动jar包,在模块中新建libs文件夹,将jar包拖入
//右键libs文件夹-->Add as Library-->OK
//2、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//3、获取数据库连接对象Connection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、定义sql
String sql = "update account set balance = 50 where id = 1";
//5、获取执行sql语句的对象
Statement stmt = conn.createStatement();
//6、执行sql
int count = stmt.executeUpdate(sql);
//7、处理结果
System.out.println(count);
//8、释放资源
stmt.close();
conn.close();
}
}
DriverManager:驱动管理对象
1、注册驱动:static void registerDriver(Driver driver)注册与给定的驱动程序DriverManager
写代码使用:Class.forName("com.mysql.cj.jdbc.Driver");
通过源码发现,在com.mysql.cj.jdbc.Driver类中存在静态代码块。==mysql5之后的驱动jar包可以省略注册驱动的步骤==
2、获取数据库连接:static Connection getConnection(String url,String user,String password)
url:指定连接的路径
user:用户名
password:密码
Connection:数据库连接对象
1、获取指定sql对象:
Statement createStatememt()
ProparedStatement perpareStatement(String sql)
2、管理事务:
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
提交事务:commit()
回滚事务:rollback()
Statement:执行sql的对象
1、boolean execute(String sql):可以执行任意的sql
2、int executeUpdate(String sql):执行DML、DDL语句
==返回值是影响的行数==判断DML语句是否执行成功,赶回值>0则执行成功,反之失效
3、ResultSet executeQuery(String sql):执行DQL语句,返回值为一个结果集对象。
ResultSet:结果集对象
PerparedStatement:执行sql的对象
JDBC之CRUD练习
account表:添加一条记录,insert语句
public class jdbcDemo02 {
public static void main(String[] args) {
//在finally中释放资源的时候因为对象定义在try中,所以要在外边单独定义
Statement stmt = null;
Connection conn = null;
//1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2、定义sql
String sql = "insert into account values(null,'王五',3000)";
//3、获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、获取执行sql的对象Statream
stmt = conn.createStatement();
//5、执行sql
int count = stmt.executeUpdate(sql);//影响的行数
//6、处理结果
System.out.println(count);
if (count>0){
System.out.println("添加成功!");
}else {
System.out.println("添加失败");
}
//
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
account表:修改一条记录,update语句
public class jdbcDemo03 {
public static void main(String[] args) {
//在finally中释放资源的时候因为对象定义在try中,所以要在外边单独定义
Statement stmt = null;
Connection conn = null;
//1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2、定义sql
String sql = "update account set balance = 1500 where id = 3";
//3、获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、获取执行sql的对象Statream
stmt = conn.createStatement();
//5、执行sql
int count = stmt.executeUpdate(sql);//影响的行数
//6、处理结果
System.out.println(count);
if (count>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败");
}
//
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
account表:删除一条记录,delete语句
public class jdbcDemo04 {
public static void main(String[] args) {
//在finally中释放资源的时候因为对象定义在try中,所以要在外边单独定义
Statement stmt = null;
Connection conn = null;
//1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2、定义sql
String sql = "delete from account where id = 3 ";
//3、获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、获取执行sql的对象Statream
stmt = conn.createStatement();
//5、执行sql
int count = stmt.executeUpdate(sql);//影响的行数
//6、处理结果
System.out.println(count);
if (count>0){
System.out.println("删除成功!");
}else {
System.out.println("删除失败");
}
//
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
ResultSet类详解
ResultSet:结果集对象,封装查询结果
next():游标向下移动一行,判断当前行是否是最后一行末尾,如果是,则返回false,如果不是返回true
getXxx(参数):获取数据
Xxx:代表数据类型,如:int getInt(),String getString()
参数:int:代表列的编号,从1开始 如:getInt(1)
String:代表列名称。如:getDouble(“balance”)
//account表:查询第一行的数据
public class jdbcDemo05 {
public static void main(String[] args) {
//在finally中释放资源的时候因为对象定义在try中,所以要在外边单独定义
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
//1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2、定义sql
String sql = "select * from account ";
//3、获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、获取执行sql的对象Statream
stmt = conn.createStatement();
//5、执行sql
rs = stmt.executeQuery(sql);//返回结果集
//6、处理结果
//6.1让游标向下移动一行
rs.next();
//6.2获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + name +balance);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
ResultSet结果集遍历
以上代码存在问题:游标向下移动一行,如果没有数据库中没有数据则会向下一行获取数据就会报错所以判断当前行是否是最后一行末尾,如果是,则返回false,如果不是返回true
但并不知数据库有多少行,所以需要遍历
1、游标应该向下移动一行
2、判断是否有数据
3、获取数据
//account表:查询遍历所有的数据
public class jdbcDemo06 {
public static void main(String[] args) {
//在finally中释放资源的时候因为对象定义在try中,所以要在外边单独定义
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
//1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2、定义sql
String sql = "select * from account ";
//3、获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//4、获取执行sql的对象Statream
stmt = conn.createStatement();
//5、执行sql
rs = stmt.executeQuery(sql);//返回结果集
//6、处理结果
//6.1让游标向下移动一行
while (rs.next()){
//循环判断结果集是否有下一行,即游标是否为最后一行末尾
//有则获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + name +balance);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
定义一个方法,查询表中的数据将其封装为对象,装载集合然后打印
1、 定义emp类
2、定义方法 pubic list findAll(){}
3、实现方法select * from emp;
封装Emp表的javaBean
public class Emp {
private int id;
private String NAME;
private String gender;
private double salary;
private Date join_date;
private int dept_id;
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", NAME='" + NAME + '\'' +
", gender='" + gender + '\'' +
", salary=" + salary +
", join_date=" + join_date +
", dept_id=" + dept_id +
'}';
}
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;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getJoin_date() {
return join_date;
}
public void setJoin_date(Date join_date) {
this.join_date = join_date;
}
public int getDept_id() {
return dept_id;
}
public void setDept_id(int dept_id) {
this.dept_id = dept_id;
}
}
定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回
public class jdbcDemo07 {
public static void main(String[] args) {
List<Emp> list = new jdbcDemo07().findAll();
System.out.println(list);
}
//查询所有Emp对象
public List<Emp> findAll(){
//变量抽取,为了释放资源
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
List<Emp> list = null;
try {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC","root","root");
//3、定义sql
String sql = "select * from emp";
//4、获取执行sql对象
stmt = conn.createStatement();
//5.执行sql
rs = stmt.executeQuery(sql);
//6、遍历结果集,封装对象,装载集合
Emp emp = null;//使emp对象进行复用,不用在while中因为创建很多emp对象而占用更多的栈内存引用
list = new ArrayList<Emp>();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("NAME");
String gender = rs.getString("gender");
double salary = rs.getDouble("salary");
Date join_date = rs.getDate("join_date");
int dept_id = rs.getInt("dept_id");
//封装emp对象,会占用很多栈内存的引用
//创建emp对象,并赋值
emp = new Emp();
emp.setId(id);
emp.setNAME(name);
emp.setGender(gender);
emp.setSalary(salary);
emp.setJoin_date(join_date);
emp.setDept_id(dept_id);
//装载集合
list.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
//stmt.close();如果这样写在获取Connection对象时发生密码错误等问题,程序就会直接跳转进入catch中,stmt是不会被执行的
//发生错误时,就会因为stmt对象因为null发生空指针异常
if (rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return list;
}
}
抽取JDBC工具类
JDBC工具类
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
//文件的读取,只需要读取一次即可拿到这些集合。使用静态代码块
static {
//读取资源文件,获取值
try {
//1、创建Properties集合类
Properties pro = new Properties();
//获取src路径下文件的方式-->ClassLoader:类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println(path);
//2、加载文件
pro.load(new FileReader(path));
//3、获取属性,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4、注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接,返回连接对象
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
//释放资源的方法
public static void close(Statement stmt,Connection conn){
//这里的两个资源释放不能放在同一个try catch中,因为如果第一个报错,第二个资源也是不能被释放的
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//重载释放资源的方法,使DQl查询的ResultSet资源得以释放
public static void close(ResultSet rs,Statement stmt, Connection conn){
//这里的两个资源释放不能放在同一个try catch中,因为如果第一个报错,第二个资源也是不能被释放的
if (rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
配置文件
url = jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC
user = root
password = root
driver = com.mysql.cj.jdbc.Driver
实体测试类
//定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回
public class jdbcDemo08 {
public static void main(String[] args) {
List<Emp> list = new jdbcDemo08().findAll1();
System.out.println(list);
}
//演示工具类
public List<Emp> findAll1(){
//变量抽取,为了释放资源
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
List<Emp> list = null;
try {
conn = JDBCUtils.getConnection();
//3、定义sql
String sql = "select * from emp";
//4、获取执行sql对象
stmt = conn.createStatement();
//5.执行sql
rs = stmt.executeQuery(sql);
//6、遍历结果集,封装对象,装载集合
Emp emp = null;//使emp对象进行复用,不用在while中因为创建很多emp对象而占用更多的栈内存引用
list = new ArrayList<Emp>();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("NAME");
String gender = rs.getString("gender");
double salary = rs.getDouble("salary");
Date join_date = rs.getDate("join_date");
int dept_id = rs.getInt("dept_id");
//封装emp对象,会占用很多栈内存的引用
//创建emp对象,并赋值
emp = new Emp();
emp.setId(id);
emp.setNAME(name);
emp.setGender(gender);
emp.setSalary(salary);
emp.setJoin_date(join_date);
emp.setDept_id(dept_id);
//装载集合
list.add(emp);
}
}
catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7、释放资源
JDBCUtils.close(rs,stmt,conn);
}
return list;
}
}
登录案例
//通过键盘输入用户名和密码
//判断用户是否登录成功
public class jdbcDemo09 {
public static void main(String[] args) {
//键盘录入,接收用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//2、调用方法
boolean flag = new jdbcDemo09().login(username, password);
//3、判断结果,输出不同语句
if (flag){
System.out.println("登录成功");
}else{
System.out.println("用户名和密码错误");
}
}
//登录方法
public boolean login(String username,String password){
if (username == null || password == null){
return false;
}
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
//连接数据库,判断是否登录成功
//1、获取连接
try {
conn = JDBCUtils.getConnection();
//2、定义sql
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
//3、获取执行sql对象
stmt = conn.createStatement();
//4、执行查询
rs = stmt.executeQuery(sql);
//5、判断
return rs.next();//如果有下一行返回true
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.close(rs,stmt,conn);
}
return false;
}
}
PerparedStatement:执行sql的对象
以上登录案例中用户名随便,密码使用a’ or ‘a’ = 'asql注入也可成功登录。
解决sql注入问题:使用 PerparedStatement对象来解决
预编译的sql:参数使用?作为占位符
使用 PerparedStatement步骤
public class jdbcDemo09 {
public static void main(String[] args) {
//键盘录入,接收用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//2、调用方法
boolean flag = new jdbcDemo09().login(username, password);
//3、判断结果,输出不同语句
if (flag){
System.out.println("登录成功");
}else{
System.out.println("用户名和密码错误");
}
}
//登录方法
public boolean login(String username,String password){
if (username == null || password == null){
return false;
}
PreparedStatement pstmt = null;
Connection conn = null;
ResultSet rs = null;
//连接数据库,判断是否登录成功
//1、获取连接
try {
conn = JDBCUtils.getConnection();
//2、定义sql
String sql = "select * from user where username = ? and password = ?";
//3、获取执行sql对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
//4、执行查询
rs = pstmt.executeQuery();
//5、判断
return rs.next();//如果有下一行返回true
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.close(rs,pstmt,conn);
}
return true;
}
}
事务管理
//事务操作
public class jdbcDemo10 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
//1、获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//2、定义sql
//2.1张三-500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2张三+500
String sql2 = "update account set balance = balance + ? where id = ?";
//3、获取执行对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4、设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5、执行sql
pstmt1.executeUpdate();
//手动制造异常
//int i = 3/0;
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception throwables) {
//事务回滚
try {
if((conn !=null)) {
conn.rollback();
}
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
}
数据库连接池
概念:就是一个容器(集合),存放数据库连接的容器
当系统初始化好之后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。
优势:节约系统资源、高效
标准接口:DataSource java.sql包下
获取连接:getConnection()
归还连接:如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。
数据库连接池分类
C3P0:数据库连接池技术
Druid:数据库连接池实现技术,由阿里巴巴提供
C3P0连接池技术
使用步骤:
1、导入c3p0-0.9.5.2.jar、mchange-commons-java-0.2.12.jar两个jar包
2、定义配置文件:c3p0.properties 或者 c3p0-config.xml
路径:直接将文件放在src目录下即可。
3、创建核心对象:数据库连接池对象ComboPooledDataSource
4、获取连接:getConnection
public class C3P0Demo01 {
public static void main(String[] args) throws SQLException {
//1、创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
//2、获取连接对象
Connection conn = ds.getConnection();
//3、打印
System.out.println(conn);
}
}
配置文件
c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db2?serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<!-- 初始化申请的连接数量 -->
<property name="initialPoolSize">5</property>
<!-- 最大的连接数量 -->
<property name="maxPoolSize">10</property>
<!-- 超时时间 -->
<property name="checkoutTimeout">3000</property>
</default-config>
<named-config name="otherc3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
Druid连接池技术
public class druidDemo {
public static void main(String[] args) throws Exception {
//1、导入jar包
//2、定义配置文件
//3、加载配置文件
Properties pro = new Properties();
InputStream is = druidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4、获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5、获取连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
druid.properties配置文件
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db2?serverTimezone=UTC
username=root
password=root
#初始化连接数量
initialSize=5
#最大连接数量
maxActive=10
#最大等待时间
maxWait=3000
minIdle=3
validationQuery:SELECT 1
testWhileIdle:true
testOnBorrow:false
testOnReturn:fal
Druid连接池工具类
public class JDBCUtils {
//1、定义一个成员变量 DataSource
private static DataSource ds;
static {
try {
//1、加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2、获取DataSource
try {
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//释放资源
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();//归还连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(ResultSet rs,Statement stmt, Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();//归还连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//获取连接池方法
public static DataSource getDataSource(){
return ds;
}
}
public class druidDemo01 {
public static void main(String[] args) {
PreparedStatement pstmt = null;
Connection conn = null;
//完成一个添加的操作,给account表添加一条记录
//1、获取连接
try {
conn = JDBCUtils.getConnection();
//2、定义sql
String sql = "insert into account values(null,?,?)";
//3、获取pstmt对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1,"王五");
pstmt.setDouble(2,3000);
//4、执行sql
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.close(pstmt,conn);
}
}
}
JDBCTemplate
update():执行DML语句,增删改语句
queryForMap():查询结果将结果即封装为map集合
queryForList():查询结果将结果集封装为list集合
query():查询结果,将结果封装为JavaBean对象
queryForObject:查询结果,将结果封装为对象
public class jdbcTemplateDemo01 {
public static void main(String[] args) {
//1、导入jar包
//2、创建jdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//3、调用方法
String sql = "update account set balance = 5000 where id = ?";
int count = template.update(sql, 3);
System.out.println(count);
}
}
练习
public class jdbcTemplateDemo02 {
//1.获取dbcTemplate对象
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//Junit单元测试,可以让方法独立执行
@Test
//修改1号数据的salary为10000
public void test1(){
//2.定义sql
String sql = "update emp set salary = 10000 where id = 1";
//3.执行sql
int count = template.update(sql);
System.out.println(count);
}
//添加一条记录
@Test
public void test2(){
String sql = "insert into emp(id,NAME,gender,salary,join_date,dept_id) values(?,?,?,?,?,?)";
int count1 = template.update(sql,7,"郭靖","男",2000,"2021-08-12",3);
System.out.println(count1);
}
// 删除刚才添加的记录
@Test
public void test3(){
String sql = "delete from emp where id = ?";
int count = template.update(sql, 7);
System.out.println(count);
}
//查询id为1的记录,将其封装为Map集合
//这个方法的结果集长度只能是1
@Test
public void test4(){
String sql = "select * from emp where id = ?";
Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
System.out.println(stringObjectMap);
}
//查询所有记录,将其封装为LIst集合
@Test
public void test5(){
String sql = "select * from emp";
List<Map<String, Object>> maps = template.queryForList(sql);
System.out.println(maps);
}
//查询所有记录,将其封装为Emp对象的List集合
@Test
public void test6(){
String sql = "select * from emp";
List<Emp> list = template.query(sql, new RowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet rs, int i) throws SQLException {
Emp emp = new Emp();
int id = rs.getInt("id");
String name = rs.getString("NAME");
String gender = rs.getString("gender");
double salary = rs.getDouble("salary");
Date join_date = rs.getDate("join_date");
int dept_id = rs.getInt("dept_id");
emp.setId(id);
emp.setNAME(name);
emp.setGender(gender);
emp.setSalary(salary);
emp.setJoin_date(join_date);
emp.setDept_id(dept_id);
return emp;
}
});
for (Emp emp : list) {
System.out.println(emp);
}
}
//查询所有记录,将其封装为Emp对象的List集合
//如果在使用时表中有null,则不能转换,需要将原本封装的类的数据类型转换为包装类
@Test
public void test7(){
String sql = "select * from emp";
List<Emp> query = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for (Emp emp : query) {
System.out.println(emp);
}
}
//查询总记录数
@Test
public void test8(){
String sql = "select count(id) from emp";
Long aLong = template.queryForObject(sql, Long.class);
System.out.println(aLong);
}
}