JDBC技术
一、介绍和理解
1、JDBC【java database connectivity】的概念:
- Java连接数据库的技术!
- Java连接数据的规范!
- JDBC由两部分组成:Java的规范【java.sql.接口】jdk、数据库厂商提供的实现类jar【实现类 基于 接口】
- Java.sql.接口=各个数据库的实现类;
2、JDBC的理解:
a.jdbc就是一套Java的规范+数据库的实现
b.我们只需要学习接口中的方法,不需要关注具体的实现!
c.可以无感切换数据库!mysql -oracle只需要切换jar即可
3、JDBC设计的接口和类
a.DriverManager
b.Driver 安装第三方数据的驱动!引入jar包
c.Connection Java陈鼓型和数据库建立的连接!在连接的基础上可以继续sql语句的执行操作
d.Statement 包装一条sql语句,发送到数据库。并待会执行结果resulteset
e.ResultSet 结果集,执行sql语句的结果的duixiang!内部的接口行和列
二、基本步骤
- 注册驱动
- 创建连接
- 创建statement
- 编写sql语句
- statement执行sql语句,并返回值
- 解析resultset数据
- 释放资源
三、基于静态Statement使用
- 非DQL(数据库查询操作)操作
//1. 注册驱动
//触发两次注册驱动!
/**
* 1. 外部注册DriverManager.registerDriver(new Driver())
* 2. 内部注册 Driver - static{ 被触发一次 }
*/
// DriverManager.registerDriver(new Driver())
// 加载类 Class.forName("字符串 类的全限定符")
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接
/**
* 获取连接:
* Java程序和数据的桥梁!
* cmd - mysql mysql -u账号 -p密码 -P port -h ip地址
* 小海豚 - mysql 账号 密码 port ip
* java - mysql 账号 密码 port ip
* url链接 - 统一资源定位符 协议 :// host : port
* jdbc:数据库厂商://ip:port/数据库?k=v
* jdbc:mysql://localhost:3306/test1 = jdbc:mysql:///test1
*
* file:///
* tpc://
* content://
* http:// 网络请求协议
* jdbc协议: jdbc:mysql jdbc:oracle
*
*/
java.sql.Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1",
"root", "root");
Properties properties = new Properties();
//传入的参数key是固定的!
properties.setProperty("user","root");
properties.setProperty("password","root");
java.sql.Connection connection_properties =
DriverManager.getConnection("jdbc:mysql://localhost:3306/test1",properties);
//url 协议 :// host : port ? key = value & key = value
java.sql.Connection connection_url =
DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?user=root&password=root");
//3. 创建statement
java.sql.Statement statement = connection.createStatement();
//4. 编写sql语句
String sql = "delete from a where aid = 1;";
//5. statement执行sql语句
//rows 返回影响行数 删除3行数据 - rows = 3
int rows = statement.executeUpdate(sql);
System.out.println("rows = " + rows);
//6. 释放资源
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
- DQL操作
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/market";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
//3.创建statement
Statement statement = connection.createStatement();
//4.写sql语句
String sql ="select * from emp";
//5.执行sql语句并获取resultset
//DQL以外的sql语句
//DML返回的影响行数! DDL TPL DCL ->0
//statement.executeUpdate();
/**
* TODO:resultSet 内部装的就是查询返回的虚拟数据表!由表头+数据组成
* TODO:数据可能没有值,但是表头绝对存在
*/
ResultSet resultSet = statement.executeQuery(sql);
//6.解析结果
/**
* todo:方案一:获取empno员工编号
* todo:移动光标
* next() return boolean
* 默认情况下,光标指向第一行数据之前,
* 移动光标可以将它指向数据!【current row】
* getString getInt getXxx getObject 获取【current row】的数据!
* return 解释,有更多行,移动光标到下一行,并返回true,如果没有更多行
* 返回false
*/
// resultSet.next();
/**
*
* todo:获取当前行的数据
* getXxx(int columnIndex[1....]/String columnlabel)
* */
// while (resultSet.next()) {
//
// String empno = resultSet.getString("empno");
// System.out.println("empno = " + empno);
//
// }
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
/**
* todo:方案二获取empno信息
*/
//表头信息 :列数和列名
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
//获取列名,不需要移动光标
//index-列的下角标,用来获取列名
//metaData.getColumnName(int index)获取列名
//metaData.getColumnLabel(int index)起别名获取别名反之列名【推荐】
while (resultSet.next()) {
//todo;列名
// resultSet.getString("empno");
// resultSet.getString("ename");
// resultSet.getString("mgr");
for (int i = 1; i <= columnCount; i++) {
//获取别名
String value = resultSet.getString(i);
String columnName = metaData.getColumnName(i);
String columnLabel = metaData.getColumnLabel(i);
System.out.println(columnName+" = " + value+" = "+columnLabel);
}
}
//7.关闭资源
resultSet.close();
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
四、基于动态Statement使用
动态模拟登陆
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");
//3、创建预编译statement
//结构sql语句!值得部分用?代替,?是站为辅的意思
String sql ="select * from USER where account =? and PASSWORD =?;";
PreparedStatement preparedStatement = connection.prepareStatement("sql");
//4、占位赋值
/**
* 参数一:?的下角标 从一开始,从左开始
*/
System.out.println("请输入账号!");
Scanner sc = new Scanner(System.in);
String account = sc.nextLine();
System.out.println("请您输入密码!");
String pwd = sc.nextLine();
preparedStatement.setObject(1,account);
preparedStatement.setObject(2,pwd);
//5、执行sql语句,不需要指明sql语句
ResultSet resultSet = preparedStatement.executeQuery();
//sql :关键字 函数 容器名 ‘字符’
//6、解析结果集
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
for (int i = 1; i < columnCount; i++) {
String string = resultSet.getString(i);
System.out.println("string = " + string);
}
}
//6、解析结果集
//7、关闭资源
resultSet.close();
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
}
五、JDBC的基本使用
1 . 返回主键编号
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");
//3、sql结构
String sql = "insert into user (nickname,account,PASSWORD)values (?,?,?)";
//4、预编译(动态statement)
PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
//5、占位符赋值
preparedStatement.setObject(1,"朱停");
preparedStatement.setObject(2,"root1");
preparedStatement.setObject(3,"root");
//6、执行sql
int rows = preparedStatement.executeUpdate();
//返回值 单行单列
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
if (rows>0) {
System.out.println("注册成功");
generatedKeys.next();
int keysInt = generatedKeys.getInt(1);
System.out.println("keysInt = " + keysInt);
}
//7、关闭资源
preparedStatement.close();
connection.close();
2 . 批量操作
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///test1?rewriteBatchedStatements=true", "root", "root");
//3.sql结构
String sql = "insert into user (nickname,account,password) values (?,?,?)";
//4.预编译动态statement
//设置想要获取返回生成keys
PreparedStatement statement = connection.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
//5.占位符赋值
statement.setObject(1, "吴邪"+i);
statement.setObject(2, "wuxie1"+i);
statement.setObject(3, "root");
statement.addBatch();
//int rows = statement.executeUpdate();
}
//6.执行sq
int[] rows = statement.executeBatch();
//
System.out.println(Arrays.toString(rows));
long end = System.currentTimeMillis();
System.out.println("time = " + (end - start));
//7.关闭资源
statement.close();
connection.close();
}
3 . 事物务操作
package com.atguigu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @description TODO:sql的实务操作
* 1、关闭自动提交 手动提交个【提交和回滚】
* show variable like "%autocommit%"#关闭了自动提交只在当前连接有效
* set autocommit = off;
* sql
* sql
* commit/rollback;
* 2、主动开启一个事务 手动提交【提交和回滚】
* start transaction;
* sql
* sql
* sql
* commit/rollback;
* jdbc的事务操作
* jdbc基于的关闭自动提交
* connection默认自动提交事物
* connection.setAutoCommit(false)
* statement connection.preparedStatment(); sql
* statement connection.preparedStatment(); sql
* connection.commit() / rollback();
* 注意: 一个事务的statement必须由同一个connection创建!
*
*
* @atuthor ${Mr.W}
* @create 2021/11/28 21:33
*/
public class jdbcTransaction {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");
//关闭自动提交
connection.setAutoCommit(false);
try {
//3、写sql语句
String sql_add ="update account set money =money+10000 where aname ='wy'";
String sql_sub ="update account set money =money-10000 where aname ='mayun'";
//4、预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql_add);
int i = preparedStatement.executeUpdate();
System.out.println("wy加钱= " + i);
PreparedStatement preparedStatement1 = connection.prepareStatement(sql_sub);
int i1 = preparedStatement1.executeUpdate();
System.out.println("mayun减钱 = " + i1);
connection.commit();
}catch (SQLException e){
e.printStackTrace();
connection.rollback();
}
//5、关闭资源
connection.close();
}
}
六、链接池使用
- 连接池介绍
- druid连接池使用
a. 直接创建 【硬编码】
```sql
private static DruidDataSource dataSource = new DruidDataSource();
static {
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///test1");
dataSource.setUsername("root");
dataSource.setPassword("root");
//3.设置可选属性,连接池的初始化容量 最大容量 等待时间【到达最大数量】
dataSource.setInitialSize(5);
dataSource.setMaxActive(10);
dataSource.setMaxWait(1000);
}
b. 工厂创建 【软编码】
private static DataSource dataSource = null;
static {
Properties properties = new Properties();
InputStream asStream = JdbcPool.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
properties.load(asStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
- druid工具类封装 [今天实现的第三个案例]
a. 编写外部配置文件
src/jdbc.properties
#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test1
username=root
password=root
initialSize=5
maxActive=10
maxWait=1000
b. 编写连接池工具类
package com.atguigu.datasource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* projectName: day04_jdbc
*
* @author: 赵伟风
* time: 2021/11/26 17:09
* description:基于Druid连接池进行连接的获取和回收!
* todo 基于外部的配置文件!
*/
public class JdbcPoolV2 {
private static DataSource dataSource = null;
static {
Properties properties = new Properties();
InputStream asStream = JdbcPool.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
properties.load(asStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接连接的方法
* @return 返回连接池中的连接
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 回收连接
* @param connection 需要回收的连接! 注意,必须是连接池取出的连接
* @throws SQLException
*/
public static void close(Connection connection) throws SQLException{
if (connection != null) {
connection.close();
}
}
}
七、ApacheDBUtils
- 介绍
a. jdbc 【获取连接和数据库的curd】
b. druid 【优化获取连接】
c. dbutils 【简化数据库curd】 - 非DQL
/**
* DML
*/
@Test
public void testCUD() throws SQLException {
//apache dbutils提供的数据的curd的工具api
QueryRunner queryRunner = new QueryRunner();
String sql = "insert into a (aid,aname) values (?,?);";
/**
* update DDL DML DCL TPL
* return int
* 参数:
* 1.connection
* 2.sql
* 3.Object...params ? 占位符值 可变参数!参数要和sql语句中的?顺序一一对应!
*/
//连接池
Connection connection = JdbcPoolV2.getConnection();
// = 1. 创建preparedStatement 2.setObject占位符赋值 3.执行sql executeUpdate()
int rows = queryRunner.update(connection, sql, "10", "呵呵");
System.out.println("rows = " + rows);
connection.close();
}
- DQL
/**
* apache DBUtils DQL
*/
@Test
public void testRead() throws SQLException {
//1.创建dbutils对象 queryrunner
QueryRunner queryRunner = new QueryRunner();
String sql = "select * from a where aid > ?;";
/**
* query执行查询语句!
* 参数1: connection
* 参数2: sql
* 参数3: rsh -> ResultSetHandler 结果集处理器 - table - class 一行数据 - 一个对象 resultSet -> 想要的结果
* 1.返回一个map
* select * from a where aid = 1;
* aid aname
* 1 xx
* map - aid - 1 / aname - xx
* 参数4: Object...params
*
*/
Connection connection = JdbcPoolV2.getConnection();
// queryRunner.query = 1.创建statement 2.占位符 3.执行sql语句 4.结果集解析
// Map<String, Object> map = queryRunner.query(connection, sql, new MapHandler(), 1);
List<Map<String, Object>> list = queryRunner.query(connection, sql, new MapListHandler(), 1);
System.out.println("list = " + list);
connection.close();
}
/**
* 查询数据库数据使用对象接值
* @throws SQLException
*/
@Test
public void testReadToEntity() throws SQLException {
//1.创建dbutils对象 queryrunner
QueryRunner queryRunner = new QueryRunner();
String sql = "select * from a where aid > ?;";
Connection connection = JdbcPoolV2.getConnection();
/**
* 如果想要返回对象请使用 BeanHandler / BeanListHandler(class)
*/
List<A> a = queryRunner.query(connection, sql, new BeanListHandler<>(A.class), 1);
System.out.println("a = " + a);
connection.close();
}