JDBCAPI
一、JDBCAPI1、JDBC的概念Java DataBase ConnectivityJDBC是官方(sun公司)定义的一套操作所有关系型数据库的接口,厂商实现这套接口(数据库驱动jar包)。2、API1、注册驱动2、获取数据库连接对象 Connection3、定义sql4、获取执行sql语句的对象 Statement,Pre(防止sql注入,预处理对象)5、执行sql,...
·
一、JDBCAPI
1、JDBC的概念
Java DataBase Connectivity
JDBC是官方(sun公司)定义的一套操作所有关系型数据库的接口,厂商实现这套接口(数据库驱动jar包)。
2、API
1、注册驱动
2、获取数据库连接对象 Connection
3、定义sql
4、获取执行sql语句的对象 Statement,Pre(防止sql注入,预处理对象)
5、执行sql,接受返回结果
6、处理结果(封装到对象中等)
7、释放资源
// 底层API使用规范。学会封装 | 使用工具
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql:127.0.0.1:3306/db_temp", "root", "root");
// 定义sql语句
String sql = "update account set xx = xx where id = 1";
// 获取执行sql的对象
StatementStatement stmt = conn.createStatement();
// 执行sql,操作影响行数
int count = stmt.executeUpdate(sql);
// 处理判断
assert count > 0;
// finally,release,must
stmt.close();
conn.close();
3、释放资源
Statement stmt = null;
Connection conn = null;
try {
// 处理结果
assert count > 0;
System.out.println(count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
// stmt.close();
// 释放资源
// 避免空指针异常
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4、API说明
4.1、连接和执行对象
// DriverManager:获取数据库连接对象
// Connection:数据库连接对象,获取执行sql语句的对象,事物管理
//-------------事物控制--------------
conn.setAutoCommit(boolean autoCommit)
//关闭自动事务管理
conn.commit()
conn.rollback()
//------------sql执行对象
Statement createStatement();
PreparedStatement prepareStatement(String sql);
// 解决sql注入
// 执行sql的方法
boolean execute(String sql);
// 可以执行任意的sql 了解
// 增删改操作
int executeUpdate(String sql);
// 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
// 查操作
ResultSet executeQuery(String sql); // 执行DQL(select)语句
4.2、获取查询结果集
// 执行sql语句,返回结果集ResultSet
// 结果集的封装
boolean next();
// 结果集遍历的方法
while(rs.next()){
// 有下一行数据:返回true
int id = rs.getInt(1); // 括号:index
String name = rs.getString("name"); // 括号:fieldName
double balance = rs.getDouble(3);
System.out.println(id + "---" + name + "---" + balance);
}
5、解决sql注入问题
利用sql中的一些语法规则、特殊符号–让服务器跳过(忽略)对某一部分数据的校验。
select * from user where name = +' + 变量 + ' + and password = +'+ 变量 +';
变量 = xx'or 1 = 1 --select * from user where name = 'xx' or 1 = 1 --' + and password = +'+ 变量 +';
//----------解决方式--------------
// 使用PreparedStatement对象来解决
// 预编译的SQL:参数使用?作为占位符
// 见事务控制部分
6、结果封装
查询操作,得到到一行一行的结果集。
// 定义User类:实体类(类名、属性名和数据库名、字段名对应)
// public List<User> findAll(){}
// 实体类对象userObj
// 查询数据集合,ResultSet
// 字段遍历,赋值给实体类对象
userObj.setName(re.getString("name"))
// 实现方法
select * from user;
List<User> list = new List<User>;
// 全局·集合
while (rs.next()) {
User obj = new User();
// 实体类对象
// 获取数据
int id = rs.getInt(1); // index
String name = rs.getString("name"); // or fieldName
double balance = rs.getDouble(3);
// 封装数据
obj.setId(id);
obj.setName(name);
obj.setBalance(balance);
System.out.println(obj);
// toString方法
// 对象放到集合中
list.append(obj);
}
// 循环结束,数据封装完成
// 遍历集合:增强for
二、冗余封装
1、封装工具类 将数据库信息封装到一个配置文件中,通过类加载器进行解析,完成数据库配置,对外提供一个返回数据库连接的方法。
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
// 静态代码块:类初始化仅仅加载一次。(静态变量、父类非静态、父类静态代码块、父类构造、子···)
static {
try {
ClassLoader classLoader = JDBCUtils.class.getClassLoader(); // 类加载器获取配置文件
// properties文件 Java文件式式数据结构
URL res = classLoader.getResource("jdbc.properties");
assert res != null;
String path = res.getPath();
System.out.println(path);
// Properties集合类
Properties pro = new Properties();
pro.load(new FileReader(path));
// 获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
// 注册驱动
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
// 对外提供一个方法,调用方法返回数据库连接conn
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password); // 返回:conn
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
// 资源释放,可能没有Result,但是Statement、Connection都有,可以使用方法重载(参数不同)
}
}
Connection conn = JDBCUtils.getConnection();
2、释放资源(完善)
调用工具类中的释放资源的方法(释放结果对象、sql执行对象、数据库连接对象)
// 调用使用方式
JDBCUtils.close(null,stmt,conn);
// DML(增删改)操作,没有查询结果集
JDBCUtils.close(rs,stmt,conn);
public class JDBCUtils {
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
三、事物控制
一般的都是基于同一个conn
,如果涉及到多个服务(多个数据库):查看分布式事务管理。复习MySQL事务部分。
1、说明
// 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
// 使用Connection对象来管理事务
// 开启事务:
setAutoCommit(false); // 手动
// sql语句
// 提交事务:
commit();
// 回滚事务:
rollback(); // 在catch中回滚事务
2、小案例(防止sql注入)
class JDBCDemo {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
// 1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql1 = "update account set balance = balance - ? where id = ?";
String sql2 = "update account set balance = balance + ? where id = ?";
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
pstmt1.setDouble(1, 500);
pstmt1.setInt(2, 1);
pstmt2.setDouble(1, 500);
pstmt2.setInt(2, 2);
pstmt1.executeUpdate();
// 手动制造异常
int i = 1 / 0;
pstmt2.executeUpdate();
// 提交事务
conn.commit();
} catch (Exception e) {
// 事务回滚
try {
if (conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
JDBCUtils.close(null, pstmt1, conn);
}
}
}
四、数据库连接池
高效执行
1、连接池接口
// 数据库厂商实现该接口
public interface DataSource {
// 取出连接对象,厂商实现
getConnection();
// 归还对象直接调用 close();
}
2、C3P0数据库连接池
注意C3P0版本和MySQL版本,以及JDBC-url配置
// 第三方:导入2个jar包
// 定义配置文件(名字固定放到src下)
// 创建核心对象
// 获取连接getConnection();
2.1、实现配置
<!--文件名字:c3p0-config.xml-->
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db_temp?&useSSL=false&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/db3?&useSSL=false&serverTimezone=UTC</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>
2.2、实现代码
public class C3P0Demo2 { public static void main(String[] args) throws SQLException { // 获取DataSource,使用默认配置 DataSource ds = new ComboPooledDataSource(); for (int i = 1; i <= 11 ; i++) { // 获取连接 Connection conn = ds.getConnection(); System.out.println(i+":"+conn); if(i == 5){ // 归还连接到连接池中 conn.close(); } } }
3、Druid数据库连接池
// 导入jar包
// 配置文件:Properties,名字任意,路径任意,手动加载
// 获取数据库连接池对象:工厂
// 获取连接
getConnection();
3.1、配置文件
driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://192.168.3.3:33306/Demo1username=rootpassword=121388
// 初始化连接数量
initialSize=5
// 最大连接数
maxActive=10
// 最大等待时间
maxWait=3000
`##### 3.2、maven坐标
<!--版本搜索一波--><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version></version></dependency>
3.3、代码
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); }}
五、JdbcTemapate
学会使用工具
1、针对连接池设计出来的
/** 参数:一个数据库连接池对象DataSource
* 返回值:数据库连接对象Connection
* 方法封装:基础的CRUD,有JdbcTUserlate对象调用
* 方法参数:sql语句,sql参数,封装结果集的RowMapper对象(自定义)
* 优化:自动释放资源(close)
*/
2、代码
class JdbcTemplateDemo {
public static void main(String[] args) {
// 带入jar包
// 创建JdbcTUserlate对象, 把连接池传过来
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 生成sql
String sql = "select * from fruit";
// 执行方法
Object list = (Object) jdbctUserlate.queryForList(sql);
// 自动释放资源,自动归还连接到连接池
System.out.println(list);
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)