核心概述:在实际开发中,咱们须要经过Java程序来操做数据库,此时Java给咱们提供了Java访问数据库的标准规范就是JDBC,咱们能够经过调用JDBC接口中的方法实现操做数据库。java
01-使用第三方客户端来访问 MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL 。mysql
02-使用 MySQL 自带的命令行方式 。程序员
03-经过 Java 来访问 MySQL 数据库,本篇要讲解的内容spring
什么是JDBC
JDBC (Java Database Connectivity,简称JDBC )是 Java 访问数据库的标准规范,真正怎么操做数据库还须要具体的实现类,也就是数据库驱动。每一个 数据库厂商根据自家数据库的通讯格式编写好本身数据库的驱动。因此咱们只须要会调用 JDBC 接口中的方法便可,数据库驱动由数据库厂商提供。sql
JDBC的好处
01-程序员若是要开发访问数据库的程序,只须要会调用 JDBC 接口中的方法便可,不用关注类是如何实现的。数据库
02-使用同一套 Java 代码,进行少许的修改就能够访问其余 JDBC 支持的数据库 。安全
使用 JDBC 开发使用到的包
会使用到的包 | 说明 |
---|---|
java.sql |
全部与 JDBC 访问数据库相关的接口和类 |
javax.sql |
数据库扩展包,提供数据库额外的功能。如:链接池 |
数据库的驱动 |
由各大数据库厂商提供,须要额外去下载,是对 JDBC 接口实现的类 |
接口或类 | 做用 |
---|---|
DriverManager 类 |
1) 管理和注册数据库驱动 2) 获得数据库链接对象 |
Connection 接口 |
一个链接对象,可用于建立 Statement 和 PreparedStatement 对象 |
Statement 接口 |
一个 SQL 语句对象,用于将 SQL 语句发送给数据库服务器。 |
PreparedStatement 接口 |
一个 SQL 语句对象,是 Statement 的子接口 |
ResultSet 接口 |
用于封装数据库查询的结果集,返回给客户端 Java 程序 |
下载
连接:https://pan.baidu.com/s/1igjB...
提取码:v72g服务器
导入步骤
加载方法
加载和注册驱动的方法 | 描述 |
---|---|
Class.forName(数据库驱动实现类) |
加载和注册数据库驱动,数据库驱动由 mysql 厂商"com.mysql.jdbc.Driver" |
具体实现
public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //抛出类找不到的异常,注册数据库驱动 Class.forName("com.mysql.jdbc.Driver"); } }
疑问:为何这样能够注册驱动?并发
public class Driver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); //注册数据库驱动 } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }
com.mysql.jdbc.Driver 源代码:app
Driver 接口,全部数据库厂商必须实现的接口,表示这是一个驱动类。
注意事项
从 JDBC3 开始,目前已经广泛使用的版本。能够不用注册驱动而直接使用。Class.forName 这句话能够省略。
为了向下兼容,建议不要省略。
DriverManager 类中的静态方法 | 描述 |
---|---|
Connection getConnection (String url, String user, String password) |
经过链接字符串,用户名,密码来获得数据库的链接对象 |
Connection getConnection (String url, Properties info) |
经过链接字符串,属性对象来获得链接对象 |
参数 | 说明 |
---|---|
用户名 | 登陆的用户名 |
密码 | 登陆的密码 |
链接字符串 URL | 不一样的数据库 URL 是不一样的 mysql 的写法 jdbc:mysql://localhost:3306/数据库[?参数名=参数值] |
驱动类的字符串名 | com.mysql.jdbc.Driver |
格式
协议名:子协议://服务器名或 IP 地址:端口号/数据库名?参数=参数值
MySQL格式
MySQL简写格式
前提:必须是本地服务器,端口号是 3306 。
简写格式:jdbc:mysql:///数据库名
乱码的处理
若是数据库出现乱码,能够指定参数: ?characterEncoding=utf8
,表示让数据库以 UTF-8 编码来处理数据。
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
方式1:使用用户名、密码、URL 获得链接对象
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 获得链接对象 */ public class Demo2 { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/db3"; //1) 使用用户名、密码、URL 获得链接对象 Connection connection = DriverManager.getConnection(url, "root", "root"); //com.mysql.jdbc.JDBC4Connection@68de145 System.out.println(connection); } }
方式2:使用属性文件和 url 获得链接对象
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class Demo3 { public static void main(String[] args) throws SQLException { //url 链接字符串 String url = "jdbc:mysql://localhost:3306/db3"; //属性对象 Properties info = new Properties(); //把用户名和密码放在 info 对象中 info.setProperty("user","root"); info.setProperty("password","root"); Connection connection = DriverManager.getConnection(url, info); //com.mysql.jdbc.JDBC4Connection@68de145 System.out.println(connection); } }
做用
Connection 接口,具体的实现类由数据库的厂商实现,表明一个链接对象。
方法
方法 | 描述 |
---|---|
Statement createStatement() |
建立一条 SQL 语句对象 |
表明一条语句对象,用于发送 SQL 语句给服务器,用于执行静态 SQL 语句并返回它所生成结果的对象。
Statement 接口中的方法 | 描述 |
---|---|
int executeUpdate(String sql) |
用于发送 DML 语句,增删改的操做(insert、update、delete) 参数:SQL 语句 返回值:返回对数据库影响的行数 |
ResultSet executeQuery(String sql) |
用于发送 DQL 语句,执行查询的操做。 select 参数:SQL 语句 返回值:查询的结果集 |
需求:使用 JDBC 在 MySQL 的数据库中建立一张学生表
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 建立一张学生表 */ public class Demo4DDL { public static void main(String[] args) { //1. 建立链接 Connection conn = null; Statement statement = null; try { conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //2. 经过链接对象获得语句对象 statement = conn.createStatement(); //3. 经过语句对象发送 SQL 语句给服务器 //4. 执行 SQL statement.executeUpdate("create table student (id int PRIMARY key auto_increment, " + "name varchar(20) not null, gender boolean, birthday date)"); //5. 返回影响行数(DDL 没有返回值) System.out.println("建立表成功"); } catch (SQLException e) { e.printStackTrace(); } //6. 释放资源 finally { //关闭以前要先判断 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
需求
向学生表中添加 4 条记录,主键是自动增加
步骤
代码
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 向学生表中添加 4 条记录,主键是自动增加 */ public class Demo5DML { public static void main(String[] args) throws SQLException { // 1) 建立链接对象 Connection connection = DriverManager.getConnection("jdbc:mysql:///day24", "root", "root"); // 2) 建立 Statement 语句对象 Statement statement = connection.createStatement(); // 3) 执行 SQL 语句:executeUpdate(sql) int count = 0; // 4) 返回影响的行数 count += statement.executeUpdate("insert into student values(null, '孙悟空', 1, '1993-03- 24')"); count += statement.executeUpdate("insert into student values(null, '白骨精', 0, '1995-03- 24')"); count += statement.executeUpdate("insert into student values(null, '猪八戒', 1, '1903-03- 24')"); count += statement.executeUpdate("insert into student values(null, '嫦娥', 0, '1993-03- 11')"); System.out.println("插入了" + count + "条记录"); // 5) 释放资源 statement.close(); connection.close(); } }
ResultSet 接口
做用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。
接口中的方法:
其余方法
经常使用的数据类型转换表
java.sql.Date、Time、Timestamp(时间戳),三个共同父类是:java.util.Date
需求
确保数据库中有 3 条以上的记录,查询全部的学员信息
步骤
代码
import java.sql.*; /** * 查询全部的学生信息 */ public class Demo6DQL { public static void main(String[] args) throws SQLException { //1) 获得链接对象 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day24","root","root"); //2) 获得语句对象 Statement statement = connection.createStatement(); //3) 执行 SQL 语句获得结果集 ResultSet 对象 ResultSet rs = statement.executeQuery("select * from student"); //4) 循环遍历取出每一条记录 while(rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); boolean gender = rs.getBoolean("gender"); Date birthday = rs.getDate("birthday"); //5) 输出的控制台上 System.out.println("编号:" + id + ", 姓名:" + name + ", 性别:" + gender + ", 生日:" + birthday); } //6) 释放资源 rs.close(); statement.close(); connection.close(); } }
结果
ResultSet使用注意事项
若是一个功能常常要用到,咱们建议把这个功能作成一个工具类,能够在不一样的地方重用。
需求
上面写的代码中出现了不少重复的代码,能够把这些公共代码抽取出来
代码实现
close(Connection conn, Statement stmt)
,close(Connection conn, Statement stmt, ResultSet rs)
import java.sql.*; /** * 访问数据库的工具类 */ public class JdbcUtils { //能够把几个字符串定义成常量:用户名,密码,URL,驱动类 private static final String USER = "root"; private static final String PWD = "root"; private static final String URL = "jdbc:mysql://localhost:3306/day24"; private static final String DRIVER= "com.mysql.jdbc.Driver"; /** * 注册驱动 */ static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获得数据库的链接 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL,USER,PWD); } /** * 关闭全部打开的资源 */ public static void close(Connection conn, Statement stmt) { if (stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 关闭全部打开的资源 */ public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } close(conn, stmt); } }
create table user ( id int primary key auto_increment, name varchar(20), password varchar(20) ) insert into user values (null,'jack','123'),(null,'rose','456'); -- 登陆, SQL 中大小写不敏感 select * from user where name='JACK' and password='123'; -- 登陆失败 select * from user where name='JACK' and password='333';
写一个登陆的方法
import com.it.utils.JdbcUtils; import javax.xml.transform.Result; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class Demo7Login { //从控制台上输入的用户名和密码 public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String name = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); login(name, password); } /** * 登陆的方法 */ public static void login(String name, String password) { //a) 经过工具类获得链接 Connection connection = null; Statement statement = null; ResultSet rs = null; try { connection = JdbcUtils.getConnection(); //b) 建立语句对象,使用拼接字符串的方式生成 SQL 语句 statement = connection.createStatement(); //c) 查询数据库,若是有记录则表示登陆成功,不然登陆失败 String sql = "select * from user where name='" + name + "' and password='" + password + "'"; System.out.println(sql); rs = statement.executeQuery(sql); if (rs.next()) { System.out.println("登陆成功,欢迎您:" + name); } else { System.out.println("登陆失败"); } } catch (SQLException e) { e.printStackTrace(); } finally { //d) 释放资源 JdbcUtils.close(connection, statement, rs); } } }
现象
当咱们输入如下密码,咱们发现咱们帐号和密码都不对居然登陆成功了
请输入用户名: newboy 请输入密码: a' or '1'='1 select * from user where name='newboy' and password='a' or '1'='1' 登陆成功,欢迎您:newboy
问题分析
select * from user where name='newboy' and password='a' or '1'='1' -- name='newboy' and password='a' 为假 -- '1'='1' 真 -- 至关于 select * from user where true; -- 查询了全部记录
咱们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容做为了 SQL 语句语法的一部分,改变了 原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和咱们的 SQL 语句进 行简单的字符串拼接。
PreparedStatement 是 Statement 接口的子接口,继承于父接口中全部的方法。它是一个预编译的 SQL 语句
建立
经常使用方法
做用
"SELECT * FROM user WHERE name=? AND password=?"
;使用 PreparedStatement 改写上面的登陆程序,看有没有 SQL 注入的状况
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; /** * 使用 PreparedStatement */ public class Demo8Login { //从控制台上输入的用户名和密码 public static void main(String[] args) throws SQLException { Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String name = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); login(name, password); } /** * 登陆的方法 * @param name * @param password */ private static void login(String name, String password) throws SQLException { Connection connection = JdbcUtils.getConnection(); //写成登陆 SQL 语句,没有单引号 String sql = "select * from user where name=? and password=?"; //获得语句对象 PreparedStatement ps = connection.prepareStatement(sql); //设置参数 ps.setString(1, name); ps.setString(2,password); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { System.out.println("登陆成功:" + name); } else { System.out.println("登陆失败"); } //释放资源,子接口直接给父接口 JdbcUtils.close(connection,ps,resultSet); } }
案例:使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象
import com.it.entity.Student; import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Demo9Student { public static void main(String[] args) throws SQLException { //建立学生对象 Student student = new Student(); Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student where id=?"); //设置参数 ps.setInt(1,2); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { //封装成一个学生对象 student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); } //释放资源 JdbcUtils.close(connection,ps,resultSet); //能够数据 System.out.println(student); } }
案例:将多条记录封装成集合 List,集合中每一个元素是一个 JavaBean 实体类
需求: 查询全部的学生类,封装成 List<student>
返回
import com.it.entity.Student; import com.it.utils.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; public class Demo10List { public static void main(String[] args) throws SQLException { //建立一个集合 List<Student> students = new ArrayList<>(); Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student"); //没有参数替换 ResultSet resultSet = ps.executeQuery(); while(resultSet.next()) { //每次循环是一个学生对象 Student student = new Student(); //封装成一个学生对象 student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); //把数据放到集合中 students.add(student); } //关闭链接 JdbcUtils.close(connection,ps,resultSet); //使用数据 for (Student stu: students) { System.out.println(stu); } } }
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo11DML { public static void main(String[] args) throws SQLException { //insert(); //update(); delete(); } //插入记录 private static void insert() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)"); ps.setString(1,"小白龙"); ps.setBoolean(2, true); ps.setDate(3,java.sql.Date.valueOf("1999-11-11")); int row = ps.executeUpdate(); System.out.println("插入了" + row + "条记录"); JdbcUtils.close(connection,ps); } //更新记录: 换名字和生日 private static void update() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("update student set name=?, birthday=? where id=?"); ps.setString(1,"黑熊怪"); ps.setDate(2,java.sql.Date.valueOf("1999-03-23")); ps.setInt(3,5); int row = ps.executeUpdate(); System.out.println("更新" + row + "条记录"); JdbcUtils.close(connection,ps); } //删除记录: 删除第 5 条记录 private static void delete() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("delete from student where id=?"); ps.setInt(1,5); int row = ps.executeUpdate(); System.out.println("删除了" + row + "条记录"); JdbcUtils.close(connection,ps); } }
以前咱们是使用 MySQL 的命令来操做事务。接下来咱们使用 JDBC 来操做银行转帐的事务
CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加数据 INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo12Transaction { //没有异常,提交事务,出现异常回滚事务 public static void main(String[] args) { //1) 注册驱动 Connection connection = null; PreparedStatement ps = null; try { //2) 获取链接 connection = JdbcUtils.getConnection(); //3) 开启事务 connection.setAutoCommit(false); //4) 获取到 PreparedStatement //从 jack 扣钱 ps = connection.prepareStatement("update account set balance = balance - ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Jack"); ps.executeUpdate(); //出现异常 System.out.println(100 / 0); //给 rose 加钱 ps = connection.prepareStatement("update account set balance = balance + ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Rose"); ps.executeUpdate(); //提交事务 connection.commit(); System.out.println("转帐成功"); } catch (Exception e) { e.printStackTrace(); try { //事务的回滚 connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } System.out.println("转帐失败"); } finally { //7) 关闭资源 JdbcUtils.close(connection,ps); } } }
数据库链接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤其突出。
一个数据库链接对象均对应一个物理数据库链接,每次操做都打开一个物理链接,使用完都关闭链接,这样形成系统的 性能低下。
数据库链接池的解决方案是在应用程序启动时创建足够的数据库链接,并将这些链接组成一个链接池(简单说:在一个“池”里放了好多数据库链接对象),由应用程序动态地对池中的链接进行申请、使用和释放。
对于多于链接池中链接数的并发请求,应该在请求队列中排队等待。而且应用程序能够根据池中链接的使用率,动态增长或减小池中的链接数。
链接池技术尽量多地重用了消耗内存地资源,大大节省了内存,提升了服务器地服务效率,可以支持更多的客户服务。经过使用链接池,将大大提升程序运行效率,同时,咱们能够经过其自身的管理机制来监视数据库链接的数量、使用状况等。
数据库链接池负责分配、管理和释放数据库链接,它容许应用程序重复使用一个现有的数据库链接,而不是再从新创建一个;释放空闲时间超过最大空闲时间的数据库链接来避免由于没有释放数据库链接而引发的数据库链接遗漏。这项技术能明显提升对数据库操做的性能。
Java提供了数据库链接池接口:DataSource
javax.sql包下的。
数据库厂商实现接口,经常使用的有如下两种:
C3P0
:数据库链接池技术Druid
:数据库链接池实现技术,由阿里巴巴提供的准备资料
下载
连接:https://pan.baidu.com/s/1XAst...
提取码:450q
使用步骤
01-导入jar包 (两个) c3p0-0.9.5.2.jar
和 mchange-commons-java-0.2.12.jar
。不要忘记导入数据库驱动jar包
02-定义配置文件。
c3p0.properties
或者 c3p0-config.xml
03-建立核心对象 数据库链接池对象 ComboPooledDataSource。
04-获取数据库链接对象。
c3p0-config.xml配置文件
<c3p0-config> <!-- 使用默认的配置读取链接池对象 --> <default-config> <!-- 链接参数 --> <!--驱动--> <property name="driverClass">com.mysql.jdbc.Driver</property> <!--数据库地址--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/db2</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>
代码演示
public class Test01 { public static void main(String[] args) throws SQLException { // 建立数据库链接池对象 DataSource ds = new ComboPooledDataSource(); // 获取数据库链接对象 Connection con = ds.getConnection(); System.out.println(con); } }
准备资料
下载
连接:https://pan.baidu.com/s/1nWIF...
提取码:f43e
使用步骤
1. 导入jar包 druid-1.0.9.jar 2. 定义配置文件: * 是properties形式的 * 能够叫任意名称,能够放在任意目录下 3. 加载配置文件。Properties 4. 获取数据库链接池对象:经过工厂来来获取 DruidDataSourceFactory 5. 获取链接:getConnection
druid.properties配置文件
# 数据库驱动 driverClassName=com.mysql.jdbc.Driver # 数据库链接地址 url=jdbc:mysql://127.0.0.1:3306/db2 # 用户名 username=root # 密码 password=root # 初始化链接对象个数 initialSize=5 # 最大个数 maxActive=10 # 超时等待时长 maxWait=3000
代码
public class Test01 { public static void main(String[] args) throws Exception { Properties pro = new Properties(); InputStream is = Test01.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); DataSource ds = DruidDataSourceFactory.createDataSource(pro); Connection con = ds.getConnection(); System.out.println(con); } }
DruidUtils
package it.leilei.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class DruidUtils { private static DataSource ds; private static InputStream is; static { Properties pro = new Properties(); try { // 读取配置文件 is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); // 建立数据库链接池对象 ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }finally { if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } // 获取Connection对象 public static Connection getConnection() throws SQLException { return ds.getConnection(); } // 释放资源 public static void close(Statement sta, Connection con, ResultSet rs) { if(sta!=null){ try { sta.close(); } catch (SQLException e) { e.printStackTrace(); } } if(con!=null){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Statement sta, Connection con){ close(sta,con,null); } // 获取链接池对象 public static DataSource getDataSource(){ return ds; } }
测试:向数据库db2中的表account中添加一条新的数据
package it.leilei.DruidDemo; import it.leilei.util.DruidUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Test02 { public static void main(String[] args) { Connection con = null; PreparedStatement ps = null; try { // 获取数据库链接对象 con = DruidUtils.getConnection(); // 定义SQL String sql = "INSERT INTO account VALUES(NULL,?,?)"; // 建立执行SQL语句对象 ps = con.prepareStatement(sql); // 给参数设置值 ps.setString(1,"小龙女"); ps.setDouble(2,8000); // 执行sql int count = ps.executeUpdate(); if(count>0){ System.out.println("添加成功"); }else { System.out.println("添加失败"); } } catch (SQLException e) { e.printStackTrace(); }finally { DruidUtils.close(ps,con); } } }
以上数据库链接池确实优化并简化了Java对SQL的操做,可是在针对增删改查操做时相对仍是有些繁琐,在实际开发中,咱们一般会使用框架中封装好的JDBC来操做数据库,能够更加简化Java对SQL的操做,提升开发效率。
Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。
准备资料
下载
连接:https://pan.baidu.com/s/1JLru...
提取码:73vt
使用步骤
导入jar包(lib目录下全部jar包)
JdbcTemplate
对象。依赖于数据源DataSource。调用JdbcTemplate的方法来完成CRUD的操做
update()
:执行DML语句。增、删、改语句queryForMap()
:查询结果将结果集封装为map集合,将列名做为key,将值做为value 将这条记录封装为一个map集合
queryForList()
:查询结果将结果集封装为list集合
query()
:查询结果,将结果封装为JavaBean对象
query的参数:RowMapper
<
类型>
(类型.class)queryForObject:查询结果,将结果封装为对象
代码演示
package it.leilei.JDBCTemplateDemo; import it.leilei.domain.Emp; import it.leilei.util.DruidUtils; import org.junit.Test; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; public class Test01 { // 建立JdbcTemplate对象 private JdbcTemplate jt = new JdbcTemplate(DruidUtils.getDataSource()); /* 添加一条新的数据 */ @Test public void test01(){ // 定义SQL String sql = "INSERT INTO emp(NAME,gender,salary)VALUES(?,?,?)"; // 执行 int i = jt.update(sql,"张三丰","男",90000); System.out.println(i); } /* 更新一条数据 */ @Test public void test02(){ String sql = "update emp set salary=? where id=1"; int i = jt.update(sql,10000); System.out.println(i); } /* 删除一条数据 */ @Test public void test03(){ String sql = "delete from emp where id=?"; int i = jt.update(sql,8); System.out.println(i); } /* * 查询一条数据返回map集合 * */ @Test public void test04(){ String sql = "select * from emp where id=?"; Map<String,Object> map = jt.queryForMap(sql,1); System.out.println(map); } /* * 查询多条数据返回List集合 * */ @Test public void test05(){ String sql = "select * from emp where id=? or id=?"; List<Map<String, Object>> list = jt.queryForList(sql,1,2); System.out.println(list); } /* * 查询多条数据返回List<Emp>集合 * */ @Test public void test06(){ String sql = "select * from emp where id=? or id=?"; List<Emp> list = jt.query(sql,new BeanPropertyRowMapper<Emp>(Emp.class),1,2); System.out.println(list); } /* * 聚合函数 * */ @Test public void test07(){ String sql = "select count(id) from emp"; long l = jt.queryForObject(sql,Long.class); System.out.println(l); } }