JDBC
一、概述
二、理解
三、JDBC API
四、JDBC的使用
private static void queryAll() throws ClassNotFoundException, SQLException {
// 1、加载驱动
// DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");
// 2、获取连接 参数1:连接路径 参数2:用户名 参数3:密码
// https://downloads.mysql.com/archives/c-j/
Connection connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/java0210", "root", "123456");
System.out.println(connection);
System.out.println(connection==null?"连接失败":"连接成功");
//3、 编写sql语句
String sql = "select * from user";
//4、创建命令对象
Statement statement = connection.createStatement();
//5、执行sql语句 返回结果
ResultSet rs = statement.executeQuery(sql);
//6、处理结果 rs.next()如果为true 集合中还有内容 如果为false 数据获取完毕
while(rs.next()){
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("姓名:"+name+"\t姓名:"+age);
// System.out.println(rs.getString("name")+" 年龄:"+rs.getInt("age"));
}
//7、释放资源 遵循 先开后关原则
rs.close();
statement.close();
connection.close();
}
五、连接池
5.1、为什么使用连接池
5.2、连接池原理
5.3、连接池的好处
5.4、常见的开源连接池
5.5、连接池的使用
5.5.1、c3p0连接池
代码配置⽅式
//1、创建连接池对象
ComboPooledDataSource cpds = new ComboPooledDataSource();
#必配信息
c3p0.driverClass = com.mysql.jdbc.Driver
c3p0.jdbcUrl = jdbc:mysql://localhost:3306/java0210
c3p0.user = root
c3p0.password = 123456
#选配
c3p0.InitialPoolSize = 10 #初始连接数
c3p0.MaxPoolSize = 200 #最大连接数
c3p0.MinPoolSize = 15 #最小连接数
c3p0.MaxIdleTime = 30 #最大空闲时间
//从池子中获取连接
Connection connection = cpds.getConnection();
//1、编写sql
String sql = "select * from user where age = 23";
//2、创建命令对象
Statement statement = connection.createStatement();
//3、执行命令 返回结果
ResultSet resultSet = statement.executeQuery(sql);
//4、处理结果
if (resultSet.next()){
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("姓名:"+name+"\t姓名:"+age);
}
//5、把连接对象放回连接池
connection.close();
5.5.2、Druid连接池
#必配
driver.ClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/java0210
username = root
password = 123456
#选配
initialSize = 15 #初始连接数
maxActive = 100 #最大连接数
minIdle = 5 #最小连接数
maxWait = 30000 #最大空闲时间
// 一、读取配置文件
Properties properties = new Properties();
// 根据当前线程对象的上下文类加载器 以流的方式 读取src目录下的文件
InputStream asStream = Thread.currentThread()
.getContextClassLoader().getResourceAsStream("druid.properties");
properties.load(asStream);
// 二、创建druid连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//从池子中获取连接
Connection connection = dataSource.getConnection();
//1、编写sql
String sql = "select * from user where age = 23";
//2、创建命令对象
Statement statement = connection.createStatement();
//3、执行命令 返回结果
ResultSet resultSet = statement.executeQuery(sql);
//4、处理结果
if (resultSet.next()){
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("姓名:"+name+"\t姓名:"+age);
}
//5、把连接对象放回连接池
connection.close();
5.6、封装JDBCTools
ThreadLocal类
public class JDBCPoolTools2 {
static DataSource dataSource;
// 实例化ThreadLocal类
private static ThreadLocal<Connection> t = new ThreadLocal<>();
static {
try{
// 一、读取配置文件
Properties properties = new Properties();
// 根据当前线程对象的上下文类加载器 以流的方式 读取src目录下的文件
InputStream asStream = Thread.currentThread()
.getContextClassLoader().getResourceAsStream("druid.properties");
properties.load(asStream);
//2、创建连接池
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 定义一个获取连接的静态方法
public static Connection getConnection(){
try {
//1、从连ThreadLocal中获取连接
Connection connection = t.get();
if (connection==null){
//2、如果连接为空,从连接池中获取一个连接对象
t.set(dataSource.getConnection());
//3、把这个连接对象绑定到ThreadLocal类
connection = t.get();
}
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//封装释放连接对象的方法
public static void release(){
// 1、将连接对象 和 ThreadLocal类 解绑
Connection connection = t.get();
t.remove();
// 2、释放资源
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
测试类
public static void main(String[] args) {
// 建立连接 从JDBCPoolTools2中调用 getConnection()方法
Connection connection = JDBCPoolTools2.getConnection();
try {
// sql操作
String sql = "select * from admin_user";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println("账号:"+username+"\t密码:"+password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
// 必须必须【解绑】和【释放资源】,从JDBCPoolTools2中调用 release()方法
if (connection!=null){
Up_DruidPool_03.release();
}
}
}
六、juint
6.1、概述
6.2、使用
6.3、常见注解
七、SQL注入
7.1、理解
7.2、解决
public class JDBCTest2 {
String username;
String pwd;
Connection connection;
@Before
public void bef(){
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名:");
username = input.nextLine();
System.out.println("请输入密码:");
pwd = input.nextLine();
connection = JDBCTools.getConnection();
}
@Test // 使用Statement
public void testLogin1(){
// 根据用户名和密码查询用户
try {
// select * from user where name='大洋洋' and password='123321';
String sql = "select * from user where name='"+username+"' and password='"+pwd+"'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
System.out.println(resultSet.next()?"登录成功!":"登录失败!");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Test // 使用PreparedStatement
public void testLogin2(){
try {
// 1. 编写sql语句
String sql = "select * from user where name=? and password=?";
// 2. 创建命令对象 预编译sql语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 3. 传递sql中的参数
preparedStatement.setString(1, username);
preparedStatement.setString(2, pwd);
// 4. 执行sql命令
ResultSet resultSet = preparedStatement.executeQuery();
// 5. 处理结果
System.out.println(resultSet.next()?"登录成功!":"登录失败!");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@After
public void aft(){
JDBCTools.release();
}
}
八、事务实现
public class JDBCTxTest {
Connection connection;
@Before
public void bef(){
connection = JDBCTools.getConnection();
}
@Test // 使用事务
public void textUseTx(){
try {
// 1. 设置事务提交为手动 2. 开启一个新的事务
connection.setAutoCommit(false);
String sql = "update user set money=? where uid=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setDouble(1, 900);
preparedStatement.setInt(2, 1);
preparedStatement.executeUpdate();
// 模拟异常
int i = 10/0;
preparedStatement.setDouble(1, 1100);
preparedStatement.setInt(2, 2);
preparedStatement.executeUpdate();
connection.commit();
System.out.println("转账成功!");
} catch (SQLException throwables) {
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}
}
@After
public void aft(){
JDBCTools.release();
}
}
九、批处理
9.1、概述
9.2、实现
public class JDBCBatchTest {
Connection connection;
@Before
public void bef(){
connection = JDBCTools.getConnection();
}
@Test // 使用批处理
public void textUseBatch(){
try {
String sql = "insert into user(name, password, money) values(?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
long start = System.currentTimeMillis();
for(int i=1; i<=10000; i++){
preparedStatement.setString(1,"root"+i);
preparedStatement.setString(2, i+"");
preparedStatement.setDouble(3, i);
// 保存到批处理中
preparedStatement.addBatch();
if(i%100==0){
// 执行批处理
preparedStatement.executeBatch();
// 清除批处理 便于下一次使用
preparedStatement.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("插入10000条花费的时间:"+(end-start)); // 6080
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@After
public void aft(){
JDBCTools.release();
}
}
十、DBUtils
10.1、简介
10.2、作用
10.2、常用方法
10.4、使用
QueryRunner qr = new QueryRunner();
// 执⾏增删改
int update = qr.update(connection,sql,params);
// 查询单条数据
T t = qr.query(connection,sql,new BeanHandler,params);
// 查询多条数据
List t = qr.query(connection,sql,new BeanListHandler,params);
// 查询特殊数据类型,如返回值为数量等等
Object t = qr.query(connection,sql,new ScalerHandler,params);
十一、Dao封装
11.1、介绍
11.2、作用
11.3、封装
public class BasicDao<T> {
QueryRunner qr;
{
qr = new QueryRunner();
}
// 1. 增删改方法
public int update(String sql, Object...params){
try {
return qr.update(JDBCTools.getConnection(), sql, params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 2. 查询单个
public T querySingle(String sql, Class<T> clazz, Object...params){
try {
return qr.query(JDBCTools.getConnection(), sql, new BeanHandler<>(clazz), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 3. 查询多个
public List<T> queryMore(String sql, Class<T> clazz, Object...params){
try {
return qr.query(JDBCTools.getConnection(), sql, new BeanListHandler<>(clazz), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 4. 查询个数
public Object scale(String sql, Object...params){
try {
return qr.query(JDBCTools.getConnection(), sql, new ScalarHandler<>(), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
十二、项目三层架构
12.1、理解
12.2、特点
return qr.query(JDBCTools.getConnection(), sql, new ScalarHandler<>(), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
## 十二、项目三层架构
### 12.1、理解
> 【**三层架构**】 通常意义上的三层架构就是将整个业务应⽤划分为:界⾯层、业务逻辑层、数据访问层。区分层次的⽬的即为了 “⾼内聚低耦合” 的思想。在软件体系架构设计中,分层式结构是最常⻅,也是最重要的⼀种结构。微软推荐的分层式结构⼀般分为三层,从下⾄上分别为:数据访问层、业务逻辑层(⼜或称为领域层)、表示层。
>
> **表示层(JSP)**
>
> 表现层也称为界⾯层,位于最外层(最上层),离⽤户最近。⽤于显示数据和接收⽤户输⼊的数据,为⽤户提供⼀种交互式操作的界⾯。
>
> **业务层(service)**
>
> * 业务层在体系架构中的位置很关键,它处于数据访问层与表示层中间,起到了数据交换中承上启下的作⽤。
>
> * 由于层是⼀种弱耦合结构,层与层之间的依赖是向下的,底层对于上层⽽⾔是“⽆知”的,改变上层的设计对于其调⽤的底层⽽⾔没有任何影响。如果在分层设计时,遵循了⾯向接⼝设计的思想,那么这种向下的依赖也应该是⼀种弱依赖关系。
>
> **持久层(DAO)**
>
> 持久层,有时候也称为是数据访问层,其功能主要是负责数据库的访问,可以访问数据库系统
### 12.2、特点
> 1、上⼀层可以调⽤下⼀层 但是 下⼀层不能调⽤上⼀层
>
> 2、不可以隔层调⽤
