概述
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
针对设问!相关问题如下:
1.什么是JDBC
2.怎么建立数据库连接(掌握)
3.关于Statement在操作数据表中的作用(了解)
4.使用PreparedStatement的 好处?具体应用方法是?(掌握)使用预编译的原因?连接数据库、操作表的步骤?
实现数据表的INSERT/UPDATE/DELETE操作
使用ResultSet和ResultSetMetaData实现数据表的SELECT操作
向数据表中插入、读取大数据:BLOB字段
INSERT / UPDATE / DELETE ; SELECT
6.数据库事务的操作方式(了解)
7.数据库连接池(理解)
C3P0数据库连接池
DBCP数据库连接池
8.JDBUtils工具类的使用(掌握)
使用QueryRunner,实现UPDATE()和QUERY()方法
利用DbUtils编写DAO通用类
解:
·1.1基础:
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API);JDBC可以连接任何提供了JDBC驱动程序的数据库系统;
·1.2 JDBC体系结构:
JDBC接口(API)包括两个层次:
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。————面向接口编程
API执行流程图:
·2 获取数据库的连接
- 实现数据库连接的前提:a.加载与注册JDBC驱动;b.数据库 url;c.user 、password
- Driver接口:
Oracle的驱动:oracle.jdbc.driver.OracleDriver
mySql的驱动: com.mysql.jdbc.Driver
a. 加载与注册JDBC驱动分为两种方式:
方式一:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动名的类Class.forName(“com.mysql.jdbc.Driver”);
方式二:DriverManager 类是驱动程序管理器类,负责管理驱动程序
DriverManager.registerDriver(com.mysql.jdbc.Driver);
通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例
b.url的标准构成及对应数据库的使用形式:
·对于 Oracle 数据库连接,采用如下形式:
jdbc:oracle:thin:@localhost:1521:atguigu
·对于 SQLServer 数据库连接,采用如下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
·对于 MYSQL 数据库连接,采用如下形式:
jdbc:mysql://localhost:3306/atguigu
c. User,password可以用“属性名=属性值”方式告诉数据库;
·2.2 建立连接(Connection)
分为两类共5中方式:
A类:使用驱动Driver对象建立连接
a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象
a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象
@Test
public void test() throws Exception {
//1.获取驱动
Driver driver = new com.mysql.jdbc.Driver();
//2.数据库连接的url
String url = "jdbc:mysql://localhost:3306/test";
//3.用配置流设置数据库的账户和密码
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "root");
//4.连接数据库
Connection connection = driver.connect(url,info);
System.out.println(connection);
}
b.连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象
/*
* 连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象
* 体会面向接口的编程思想
*/
@Test
public void test2() throws Exception {
//1.用驱动的全类名获取运行时类,创建Object类对象,获取驱动对象
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Object object = clazz.newInstance();
Driver driver = (Driver)object;
//2.创建url链接
String url = "jdbc:mysql://localhost:3306/test";
//3.创建配置文件设置登陆账户与密码
Properties info = new Properties();
info.getProperty("user","root");
info.getProperty("password","root");
//4.链接数据库
Connection connection = driver.connect(url,info);
System.out.println(connection);
}
B类:使用DriverMananger两个操作
* 1.注册驱动
* 2.获取连接
c.连接方式三:通过DriverMananger获取数据库的连接
@Test
public void test3() throws Exception {
//1.创建运行时类,获取驱动对象
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Object object = clazz.newInstance();
Driver driver =(Driver)object;
//2.创建url数据源
String url ="jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "root";
//3.注册驱动
DriverManager.registerDriver(driver);
//4.通过注册器 链接数据库
Connection connection = DriverManager.getConnection(url, user,password);
System.out.println(connection);
}
d.连接方式四:mysql驱动默认会进行驱动的注册
@Test
public void test4() throws Exception {
//1.创建驱动的运行时类
Class clazz =Class.forName("com.mysql.jdbc.Driver");
//2.创建数据库账号、密码、url2.创建数据库账号、密码、url源源
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "root";
/*
* mysql可以不用注册,其它的数据库必须进行注册
* 这一步不要省。
*/
//链接数据库
Connection connection =DriverManager.getConnection(url,user,password);
System.out.println(connection);
}
e.方式五:使用配置文件获取数据库的连接(配置文件中存放user、password、url、driver)
@Test
public void test5() throws Exception {
//1.从配置文件读取数据
InputStream iStream = this.getClass().getClassLoader()
.getResourceAsStream("sqlDriver.properties");
//2.创建配置文件对象
Properties ps = new Properties();
//3.加载文件内容到配置文件对象中
ps.load(iStream);
//3.从配置文件对象获取账户、密码、url、driver
String user= ps.getProperty("user");
String password = ps.getProperty("password");
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
//4.创建驱动对象
Class clazz =Class.forName(driverClass);
Object object = clazz.newInstance();
Driver driver = (Driver)object;
//5.注册驱动
DriverManager.registerDriver(driver);
//6.链接驱动
Connection connection = DriverManager.getConnection(url,user,password);
System.out.println(connection);
}
}
·3.Statement 接口的使用与弊端
a.在对数据库的数据进行增删改查之前要先进行预编译,也就是对数据进行调用,java.sql 包中有 3 个接口:Statement、 PrepredStatement、CallableStatement.
b.Statement会遭受SQL注入攻击,所以不建议使用,主要使用PreparedStatement(从Statement扩展而来)
SQL注入攻击:利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法
·4.1.PreparedStatement 的好处,及应用方法
好处:最大可能提高性能(DBServer会对预编译语句提供性能优化)、最大可能提高性能
预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。(重要)
连接数据库、操作表的步骤
释放资源:ResultSet 、 Connection PerpareStatement
关于ResultSet的说明
ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果.
调用 PreparedStatement 对象的 executeQuery() 可以得到结果集.
ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一条记录的前面.
相当于Iterator 对象的 hasNext() 和 next() 方法的结合体
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值.
例如: getInt(1), getString("name")
获取ResultSet中结果集的API常用方法:
next() 方法移动到下一行
getString() 根据占位符可获取对应的字符串数据
getInt().....套用以上格式
·4.2.ResultSetMetaData 类:
从结果集获取表结构(元数据):
ResultSetMetaData meta = rs.getMetaData();
元数据常用API:
getColumnName(int column):获取指定列的
名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
得到结果集后, 如何知道该结果集中有哪些列 ? 列名是什么 ---- 需要使用一个描述 ResultSet 的对象, 即 ResultSetMetaData
ResultSetMetaData:可以获取对应的 ResultSet 有多少列, 每一列的列名都是什么。
1.如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可
2.获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法
3.获取 ResultSet 每一列的列的别名是什么。getColumnLabel() 方法
·4.3实现数据表的INSERT/UPDATE/DELETE操作
封装连接数据库到方法中——JDBCUtils
·4.3.1 普通增删改
1.封装连接数据库到方法中
/*
* 通用的增删改
*/
public static int UID(String sql,Object ...objects) {
//1.获取数据库的链接
Connection connection=null;
//2.预编译
PreparedStatement ps=null;
//4.执行sql语句
int executeUpdate=-1;
try {
connection = JDBCUtils.getConnection();
ps = connection.prepareStatement(sql);
//3.填充数据
for (int i = 0; i < objects.length; i++) {// i 表示索引
ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符
}
executeUpdate = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
//5.关闭资源
JDBCUtils.close(connection, ps);
}
return executeUpdate;
}
/*
* 获取数据库的连接
*/
public static Connection getConnection() {
// 数据库的连接
Connection connection = null;
InputStream is = null;
try {
is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
Properties ps = new Properties();
ps.load(is);
String user = ps.getProperty("user");
String password = ps.getProperty("password");
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
// 创建Driver对象
Class clazz = Class.forName(driverClass);
Object obj = clazz.newInstance();
Driver driver = (Driver) obj;
// 注册驱动
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return connection;
}
public static void close(Connection connection,PreparedStatement ps) {
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
close(connection, ps);
if(rs !=null ) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.调用连接数据库类,填充数据,执行,关闭资源(关源封装到方法中
public class CRUDTest {
/*
* 向数据库中插入一条数据
*/
@Test
public void insert() {
//1.链接数据库
Connection connection=null;
//3.预编译
PreparedStatement ps=null;
try {
connection = JDBCUtils.getConnection();
//2.创建SQL语句
String sql = "INSERT INTO customers(NAME,EMAIL,birth)" + " VALUES(?,?,?);";
ps = connection.prepareStatement(sql);
//4.设置内容
ps.setString(1, "少培");// 第一个参数:第几个问号 第二个参数:内容
ps.setString(2, "shaopei@qq.com");
Date date = new Date(new java.util.Date().getTime());// 获取一个sql下的Date
ps.setDate(3, date);
//5.执行sql语句
ps.execute();
} catch (Exception e) {
// TODO: handle exception
}finally {
//6.关闭资源
JDBCUtils.close(connection,ps);
}
}
/*
* 删除一条件数
*/
@Test
public void delete() {
//1.获取数据库的链接
Connection connection=null;
//3.预编译
PreparedStatement ps=null;
try {
connection = JDBCUtils.getConnection();
//2.创建sql语句
String sql = "DELETE FROM customers WHERE id = ?";
ps = connection.prepareStatement(sql);
//4.填充数据
ps.setInt(1, 19);
//5.执行sql语句
int i = ps.executeUpdate();
System.out.println(i + "条语句受到影响");
} catch (Exception e) {
// TODO: handle exception
}
//6.关闭资源
JDBCUtils.close(connection, ps);
}
/*
* 修改一条件数
*/
@Test
public void update () throws Exception {
//1.获取数据库的链接
Connection connection=null;
//3.预编译
PreparedStatement ps=null;
try {
connection = JDBCUtils.getConnection();
//2.创建sql语句
String sql = "UPDATE customers SET NAME = ? WHERE id =?";
ps = connection.prepareStatement(sql);
//4.填充数据
ps.setString(1, "霍光");
ps.setInt(2, 21);
//5.执行sql语句
int executeUpdate = ps.executeUpdate();
} catch (Exception e) {
// TODO: handle exception
}finally {
//6.关闭资源
JDBCUtils.close(connection,ps);
}
}
}
2.通用增删改
1.封装连接数据库到方法中,执行语句也封装到同一个类中的方法中
/*
* 通用的增删改
*/
public static int UID(String sql,Object ...objects) {
//1.获取数据库的链接
Connection connection=null;
//2.预编译
PreparedStatement ps=null;
//4.执行sql语句
int executeUpdate=-1;
try {
connection = JDBCUtils.getConnection();
ps = connection.prepareStatement(sql);
//3.填充数据
for (int i = 0; i < objects.length; i++) {// i 表示索引
ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符
}
executeUpdate = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
//5.关闭资源
JDBCUtils.close(connection, ps);
}
return executeUpdate;
}
/*
* 获取数据库的连接
*/
public static Connection getConnection() {
// 数据库的连接
Connection connection = null;
InputStream is = null;
try {
is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
Properties ps = new Properties();
ps.load(is);
String user = ps.getProperty("user");
String password = ps.getProperty("password");
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
// 创建Driver对象
Class clazz = Class.forName(driverClass);
Object obj = clazz.newInstance();
Driver driver = (Driver) obj;
// 注册驱动
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return connection;
}
public static void close(Connection connection,PreparedStatement ps) {
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
close(connection, ps);
if(rs !=null ) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.创建sql语句及Date数据,调用连接数据库方法并调用执行方法。
public class CRUDTest2 {
/*
* 测试通用的增删改
*/
@Test
public void insert() {
//1.创建sql语句
String sql = " INSERT INTO customers(NAME,email,birth) VALUES(?,?,?)";
//2.获取日期数据
Date date =new java.sql.Date(new java.util.Date().getTime());
//3.调用通用方法,执行修改
int uid = JDBCUtils.UID(sql, "王玄策","wangxuance@qq.com",date);
//4.返回结果int
System.out.println(uid + "条语句收到影响");
}
}
·4.3.2
数据库的查找
1.普通查找
从数据库中查找一条数据或多条数据
从数据库中查找一条数据或多条数据
public class CRUDTest3 {
/*
* 从数据库中查找一条数据或多条数据
*/
@Test
public void select() throws Exception {
Customer customer = getCustomerById();
System.out.println(customer);
List <Customer> list = getCustomers();
for (Customer customer2 : list) {
System.out.println(customer2);
}
}
/*
* 查询多条数据
*/
public List<Customer>getCustomers() throws Exception {
//1.创建数据库连接
Connection connection = JDBCUtils.getConnection();
//2.创建sql语句
String sql = "select * from customers";
//3.预编译
PreparedStatement ps = connection.prepareStatement(sql);
//4.执行sql语句
ResultSet rs = ps.executeQuery();
//5.创建用于保存数据的集合
List<Customer> list = new ArrayList<>();
//6.获取数据,并将其封装的集合中
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date date = rs.getDate("birth");
Customer customer = new Customer(id,name,email,date);
list.add(customer);
}
//7.关闭资源
JDBCUtils.close(connection,ps,rs);
return list;
}
/*
* 查询一条数据
*/
public Customer getCustomerById() throws Exception {
//1.获取数据库的连接
Connection connection = JDBCUtils.getConnection();
//2.创建sql语句
String sql = "SELECT * FROM customers where id =?";
//3.预编译
PreparedStatement ps = connection.prepareStatement(sql);
//4.填充数据
ps.setInt(1, 20);
//5.执行sql语句
ResultSet rs = ps.executeQuery();// 查找的结果都已经放到ResultSet中了
Customer customer=null;
//6.从结果集中获取数据
if(rs.next()) {
int id =rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birth");
//7.封装数据到自定义类中
customer= new Customer(id,name,email,birth);
//8.输出结果
System.out.println(id + " " +name + " "+ email + " " +birth);
}
JDBCUtils.close(connection, ps,rs);
return customer;
}
}
/*
* 获取数据库的连接
*/
public static Connection getConnection() {
// 数据库的连接
Connection connection = null;
InputStream is = null;
try {
is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
Properties ps = new Properties();
ps.load(is);
String user = ps.getProperty("user");
String password = ps.getProperty("password");
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
// 创建Driver对象
Class clazz = Class.forName(driverClass);
Object obj = clazz.newInstance();
Driver driver = (Driver) obj;
// 注册驱动
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return connection;
}
public static void close(Connection connection,PreparedStatement ps) {
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
close(connection, ps);
if(rs !=null ) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.通用查找
public class JDBCUtils2 {
public static void main(String[] args) throws Exception {
//创建sql语句
String sql = "select id,name,email,birth from customers where id=?";
Customer customer = getObject(Customer.class, sql, 5);
System.out.println(customer);
sql = "select * from users where id=?";
User object = getObject(User.class, sql, 1);
System.out.println(object);
sql = "select * from users";
List <User> users = getObjects(User.class, sql);
for (User user : users) {
System.out.println(user);
}
}
/*
* 通用的查找 (只一条数据)
*
* Class<T> clazz : 运行时类的对象
*/
public static <T> T getObject(Class<T>clazz,String sql,Object ...objects) throws Exception {
//1.获取数据库的连接
Connection connection =JDBCUtils.getConnection();
//2.预编译
PreparedStatement ps = connection.prepareStatement(sql);
//3.填充数据
for(int i = 0;i<objects.length;i++) {
ps.setObject(i+1, objects[i]);
}
//4.执行sql语句
ResultSet rs = ps.executeQuery();
//5.获取元数据
ResultSetMetaData md = rs.getMetaData();
//6.获取列的数量
int columnCount = md.getColumnCount();
//7.创建运行时类的对象
T t =clazz.newInstance();
//8.while循环获取每一条数据
while(rs.next()) {//遍历每一条数据
/*
* 第一个问题 : 如何获取到表的列数
* 第二个问题 : 需要知道类中的属性
* 第个问题 : 对象中属性的名字怎么来
*/
//9.for循环获取每一列的数据并封装到自定义对象的属性中
for(int i =0;i<columnCount;i++) {
//a.通过列的索引获取列明(如果别名获取的是别名
String columnLabel=md.getColumnLabel(columnCount);
//b.通过列名获取列中的数据
Object value = rs.getObject(columnLabel);
//封装
//通过反射 - 给对象中的属性进行赋值
//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名
//通过列名就获取到了类中的对应的属性
Field declaredField = clazz.getDeclaredField(columnLabel);
declaredField.setAccessible(true);
/*
* 第一个参数 : 是给哪个对象进行赋值
* 第二个参数 : 属性值
*/
declaredField.set(t,value);
}
}
//关闭资源
JDBCUtils.close(connection,ps,rs);
return t;
}
/*
* 通用的查找 (返回多条数据
*
*/
public static <T> List<T> getObjects(Class<T>clazz,String sql,Object...objects) throws Exception{
//1.获取数据库的连接
Connection connection = JDBCUtils.getConnection();
//2.预编译
PreparedStatement ps = connection.prepareStatement(sql);
//3.填充数据
for(int i= 0;i<objects.length;i++) {
ps.setObject(i+1, objects[i]);
}
//4.执行sql语句
ResultSet rs = ps.executeQuery();
//5.获取元数据
ResultSetMetaData md = rs.getMetaData();
//6.获取列数
int colunmCount = md.getColumnCount();
//7.创建一个集合用于接收数据
List <T> list = new ArrayList<>();
//8.while循环获取每一条数据
while(rs.next()) {
//a.创建对象
T t = clazz.newInstance();
//b.获取每一列的列名,并且通过列明获取数据
for(int i=0;i<colunmCount;i++) {
//获取列名
String columnLabel = md.getColumnLabel(i+1);
//获取列的数据
Object value = rs.getObject(columnLabel);
//封装
//通过反射 - 给对象中的属性进行赋值
//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名
//通过列名就获取到了类中的对应的属性
Field declardField = clazz.getDeclaredField(columnLabel);
declardField.setAccessible(true);
/*
* 第一个参数 : 是给哪个对象进行赋值
* 第二个参数 : 属性值
*/
declardField.set(t, value);
}
//将对象放入集合中
list.add(t);
}
//关闭资源
JDBCUtils.close(connection, ps,rs);
return list;
}
}
·4.3.3 向数据表中插入、读取大数据:BLOB字段
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
BLOB字段由两部分组成:数据(值)和指向数据的指针(定位器)。定位器被存放在列中,值被存放在LOB段中,LOB段是在数据库内部表的一部分。在写入Blob之前,必须获得指针(定位器)才能进行写入.
如何获得Blob的指针(定位器) :需要先插入一个empty的blob,这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样通过两步操作,就获得了blob的指针,可以真正的写入blob数据了
/*
* 获取Blob类型的数据
*
* 向Blob字段中插入数据
*/
public class BlobTest {
@Test
public void insert() throws Exception{
Connection connection = JDBCUtils.getConnection();
String sql = "insert into customers(photo) values(?)";
PreparedStatement ps = connection.prepareStatement(sql);
FileInputStream fis = new FileInputStream("123.jpg");
ps.setBlob(1, fis);
boolean execute = ps.execute();
fis.close(); //关流
JDBCUtils.close(connection, ps);
}
// /*
从数据库读取数据,写到目录下
*/
@Test
public void select() throws Exception{
Connection connection = JDBCUtils.getConnection();
String sql = "select photo from customers where id = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(8, 21);
ResultSet rs = ps.executeQuery();
if(rs.next()){
Blob blob = rs.getBlob("photo");
InputStream is = blob.getBinaryStream();
FileOutputStream fos = new FileOutputStream("555.jpg");
byte[] b = new byte[1024];
int len = 0;
while((len = is.read(b)) != -1){
fos.write(b,0,len);
}
fos.close();
is.close();
}
JDBCUtils.close(connection, ps,rs);
}
}
·4.4 数据库事务
1.事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
2.事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态
3.为了让多个 SQL 语句作为一个事务执行:
调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
在出现异常时,调用 rollback(); 方法回滚事务
若此时 Connection 没有被关闭, 则需要恢复其自动提交状态
4.事务的ACID(acid)属性
a. 原子性
b. 一致性
c. 隔离性
d. 持久性、
代码:
package com.atguigu.java2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import com.atguigu.java.JDBCUtils;
/*
* 数据库事务
*/
public class Transaction {
/*
* 需求 : AA 给 BB 转账
* 第一步:AA减去100
* 第二步 :BB加上100
*
* UPDATE user_table SET balance=balance - 100 WHERE USER='AA'
UPDATE user_table SET balance=balance + 100 WHERE USER='BB'
*
* 要完成都完成,要失败都失败。
*
* 注意 :1.事务中多个sql语句必须使用同一个连接。
*/
@Test
public void test(){
String sql = " UPDATE user_table SET balance=? WHERE USER=?";
Connection connection = JDBCUtils.getConnection();
try {
//设置不让自动提交
connection.setAutoCommit(false);
UID(connection,sql, 900, "AA");
System.out.println(1 / 0);
UID(connection,sql, 1100, "BB");
connection.commit();
} catch (Exception e) {
//回滚
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/*
* 通用的增删改
*/
public int UID(Connection connection,String sql,Object ...objects) {
// 2. 预编译
PreparedStatement ps = null;
// 4.执行sql语句
int executeUpdate = -1;
try {
ps = connection.prepareStatement(sql);
// 3.填充数据
for (int i = 0; i < objects.length; i++) { // i 表示索引
ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符
}
executeUpdate = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return executeUpdate;
}
}
工具类:
package com.atguigu.java;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils {
/*
* 通用的增删改
*/
public static int UID(String sql,Object ...objects) {
// 1. 获取数据库的连接
Connection connection = null;
// 2. 预编译
PreparedStatement ps = null;
// 4.执行sql语句
int executeUpdate = -1;
try {
connection = JDBCUtils.getConnection();
ps = connection.prepareStatement(sql);
// 3.填充数据
for (int i = 0; i < objects.length; i++) { // i 表示索引
ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符
}
executeUpdate = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 5.关闭资源
JDBCUtils.close(connection, ps);
}
return executeUpdate;
}
/*
* 获取数据库的连接
*/
public static Connection getConnection() {
// 数据库的连接
Connection connection = null;
InputStream is = null;
try {
is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
Properties ps = new Properties();
ps.load(is);
String user = ps.getProperty("user");
String password = ps.getProperty("password");
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
// 创建Driver对象
Class clazz = Class.forName(driverClass);
Object obj = clazz.newInstance();
Driver driver = (Driver) obj;
// 注册驱动
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return connection;
}
public static void close(Connection connection, PreparedStatement ps) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection connection, PreparedStatement ps, ResultSet rs) {
close(connection,ps);
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
最后
以上就是天真鼠标为你收集整理的JDBC连接数据原理与事务的全部内容,希望文章能够帮你解决JDBC连接数据原理与事务所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复