JDBC基础知识笔记
0.JDBC的基础知识0.0 DBUtils 与 数据库连接池0.0.1 DBUtilsDbutils是一个对JDBC进行简单封装的开源工具类库,在学完JDBC基础后可以使用DBUtils编写一个JDBC的工具类,这样的封装可以在以后直接调用工具类来操作JDBC连接数据库,而不用繁琐的编写底层代码0.0.2 数据库连接池数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一...
0.JDBC的基础知识
0.0 DBUtils 与 数据库连接池
0.0.1 DBUtils
Dbutils是一个对JDBC进行简单封装的开源工具类库,在学完JDBC基础后可以使用DBUtils编写一个JDBC的工具类,这样的封装可以在以后直接调用工具类来操作JDBC连接数据库,而不用繁琐的编写底层代码
0.0.2 数据库连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
0.1 JDBC 是什么?
JDBC代表Java数据库连接(Java Database Connectivity),它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API,换句话说:JDBC是用于在Java语言编程中与数据库连接的API。
0.2 JDBC执行流程
1).连接数据库
2).执行需要的操作
3).关闭数据库资源
0.3 JDBC基础中用到的类或接口
0.3.1 Connection
1).Connection接口位于java.sql包当中,是与数据库连接的对象,只有获得特定的数据库连接对象,才可以访问数据库进行数据库操作。
2).void close() :用于关闭数据库连接
3).Statement createStatement() :返回一个Statement对象
4).PreparedStatement prepareStatement(String sql) :
返回PreparedStatement(预编译的Statement)对象,即将SQL语句提交到数据库进行预编译
5).void setAutoCommit(boolean autoCommit) :关闭自动提交,打开事务
6).void commit() :提交事务
7).void rollback() :回滚事务;
8).void setTransactionIsolation(int level) :设置事务的隔离级别;
0.3.2 DriverManager类
1).该类中包含了与数据库交互操作的方法,该类中的方法全部有数据库厂商提供
2). Connection getConnection(String url,Properties info) :
根据指定数据库连接URL,以及数据库连接属性信息建立数据库连接Connection。url为数据库连接URL,info是数据库连接属性。
0.3.3 Statement接口
1).Statement接口是Java程序执行数据库操作的重要接口,用于已经建立数据库连接的基础之上,向数据库发送要执行的SQL语句。它用于执行不带参数的简单SQL语句。
2).excuteUpdate int excuteUpdate(String sql) :
执行SQL语句中DML类型(insert、update、delete)的SQL语句,返回更新所影响的行数
3).ResultSet excuteQuery(String sql) :
执行查询类型(select)的SQL语句,此方法返回查询所获取的结果集ResultSet对象
4).void addBatch(String sql) :
该方法是将SQL语句添加到此Statement对象的当前命令列表中
5).void clearBatch() :
该方法是清空Statement对象中的命令列表
6).void close() :
该方法是立即释放此Statement对象的数据库和JDBC资源
0.3.4 PreparedStatement接口
1).作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能
2).void setXxx(int parameterIndex,Xxx x) :
将Xxx类型的x作为SQL语句中的参数值,parameterIndex为参数位置索引
0.3.5 Result接口
1).数据库结果集的结果表,通常通过查询数据库的语句生成
2).boolean next() :
将光标位置向后移动一行,如移动的新行有效返回true,否则返回false。
3).Xxx getXxx(String columnLabel) :
以Xxx的方式获取ResultSet对象当前行中指定列的值,参数columnLabel为列名称
1.建立数据库连接操作
1.1 versions1.0
1).创建一个Driver的对象
2).创建Properties对象接收基本信息
3).准备连接数据库的基本信息(user,password,url,driverClass)
4).调用Driver接口的connect(url,info)获取数据库连接
//1.创建一个Driver实现类的对象
Driver driver = null;
try {
driver = new com.mysql.cj.jdbc.Driver();
//2.准备连接数据库的基本信息:url,user,password
String url = "jdbc:mysql://localhost:3306/TTMS?characterEncoding=UTF8&serverTimezone=UTC";
Properties info = new Properties();
info.put("user","root");
info.put("password","123456");
//3.调用Driver接口的connect(url,info)获取数据库连接
Connection connection = driver.connect(url,info);
} catch (SQLException e) {
e.printStackTrace();
}
1.2 versions1.1
1).读取 jdbc.properties 文件
(jdbc.properties存储着创建数据库需要的基本信息)
2).创建Properties对象接收基本信息(加载对应输入流)
3).通过反射创建Driver对象
4).通过Driver的connect(url,info)获取数据库连接
String driverClass = null;
String jdbcUrl = null;
String user = null;
String password = null;
//读取 jdbc.properties 文件
InputStream in =
getClass().getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
//加载对应的输入流
properties.load(in);
driverClass = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password");
//通过反射创建 Driver对象
Driver driver = (Driver) Class.forName(driverClass).newInstance();
Properties info = new Properties();
info.put("user",user);
info.put("password",password);
//通过 Driver 的 connect 方法获取数据库连接
Connection connection = driver.connect(jdbcUrl,info);
jdbc.properties文件
driver=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/JWGL?characterEncoding=UTF8&serverTimezone=UTC
user=root
password=123456
1.3 versions1.2 (在不用数据库连接池之前的常用方法)
1).读取 jdbc.properties 文件
(jdbc.properties存储着创建数据库需要的基本信息)
2).创建Properties对象接收基本信息(加载对应输入流)
3).通过反射创建Driver对象
4).加载数据库驱动程序
5).通过DriverManager 的 getConnection() 方法获取数据库连接
/**
* Connection 代表应用程序和数据库的一个连接
*/
public static Connection getConnection() throws Exception {
//0.读取 jdbc.properties
/**
* 1).属性文件对应 Java 中的 Properties 类
* 2).可以使用类加载器加载 bin 目录(类路径下)的文件
*/
Properties properties = new Properties();
InputStream inStream =
JDBCTool01.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(inStream);
/*JDBCTool01为自己写的JDBC基础工具类,即本方法所在的类*/
//1.准备获取连接的4个字符串:driverClass,jdbcUrl,user,password
String driverClass = properties.getProperty("driver");
String jdbcUrl = properties.getProperty("jdbcUrl");
String user = properties.getProperty("user") ;
String password = properties.getProperty("password");
//2.加载驱动:Class.forName(driverClass)
Class.forName(driverClass);
//3.调用 DriverManager 的 getConnection(jdbcUrl,user,password) 方法获取数据库连接
Connection connection =
DriverManager.getConnection(jdbcUrl,user,password);
return connection;
}
1.4 versions 2.0 (通过数据库连接池建立数据库连接)
1).初始化数据库连接池
2).从数据库连接池中获取连接
dbcp.properties
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/JWGL?characterEncoding=UTF8&serverTimezone=UTC
username=root
password=123456
dbcp数据库连接池
private static DataSource dataSource = null;
//数据库连接池只初始化一次
static {
Properties properties = new Properties();
InputStream inputStream =
JDBCTool01.class.getClassLoader().getResourceAsStream("dbcp.properties");
/*JDBCTool01为自己写的JDBC基础工具类,即本方法所在的类*/
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
try {
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Connection 代表应用程序和数据库的一个连接
*/
public static Connection getConnection() throws Exception {
return dataSource.getConnection();
}
2.对数据库进行增删改操作
2.1 versions1.0 (Statement基本不用,只做入门学习)
1).获取数据库连接
2).准备插入的SQL语句
3).执行插入操作
3.1).获取操作DWL语句的Statement对象
3.2).调用Statement的 executeUpdate(sql)执行SQL语句
4).关闭数据库资源
//1.获取数据库连接
testDriver t = new testDriver(); //将获取连接的步骤封装
Connection connection = null;
Statement statement = null;
try {
connection = t.getConnection();
//2.准备插入的SQL语句
String sql ="INSERT INTO `jwgl`.`sc`(`Sno`,`Cno`,`Grade`)VALUES('2','2',1);";
//3.执行插入
//1).获取操作SQL语句的Statement对象
statement = connection.createStatement();
//2.)调用Statement 的 executeUpdate(sql)执行SQL语句
statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
//4.关闭连接
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
2.2 versions 2.0 (PreparedStatement )
1).获取数据库连接
2).准备插入的SQL语句
3).将SQL语句存入PreparedStatement对象中
4).使用PreparedStatement对象填充占位符
5).调用executeUpdate()执行SQL语句
6).关闭数据库资源
/**
* PreparedStatement : 是Statement 的子接口,可以传入带有占位符的SQL语句,
* 并且停工了补充占位符变量的方法
*/
public static void usePreparedStatement(Connection connection, String sql , Object ...args){
PreparedStatement preparedStatement = null;
try {
//1.获取PreparedStatement对象
preparedStatement = connection.prepareStatement(sql);
for(int i = 0 ; i<args.length;i++){
preparedStatement.setObject(i+1,args[i]);
}
//2.使用executeUpdate 方法 执行 SQL 语句
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
releaseDB(connection,preparedStatement,null);
}
}
2.3 PreparedStatement与Statement比的优点
1).PreparedStatement可以写动态参数化的查询
2).PreparedStatement比 Statement 更快
3).PreparedStatement可以防止SQL注入式攻击
3.对数据库的查询操作
2.1 versions1.0
1).获取数据库连接(connection)
2).获取PreparedStatement
3).准备SQL语句(将其放入PreparedStatement,并填充其占位符)
4).使用PreparedStatement的executeQuery()方法查询,并创建ResultSet的对象来接收查询结果
5).对查询结果进行想要的操作
6).关闭数据库资源
/*SC为测试的对象类*/
public static SC useResultSet(Connection connection, String sql){
Statement statement = null;
ResultSet resultSet = null;
SC sc = null;
try {
//1.获取数据库连接
//connection = getConnection();
//2.调用 Connection 对象的 createStatement() 方法获取 Statement 对象
statement = connection.createStatement();
//3.准备SQL语句
/* String sql = "SELECT Sno,Cno,Grade FROM JWGL.SC";*/
//4.调用 Statement 对象的 executeQuery() 方法,发送 SQL 语句,返回 ResultSet 结果集对象
resultSet = statement.executeQuery(sql);
//5.处理结果集
//1).调用ResultSet 的 next() 方法:查看结果集的下一条记录是否有效,有效则下移指针
while(resultSet.next()){
//2).getXxx() 方法获取具体列的值
sc = new SC();
sc.setSno(resultSet.getString(1));
sc.setCno(resultSet.getString(2));
sc.setGrade(resultSet.getInt(3));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//6.关闭数据库
releaseDB(null,statement,resultSet);
return sc;
}
2.2 versions 2.0
1).获取数据库连接(connection)
2).获取PreparedStatement
3).准备SQL语句(将其放入PreparedStatement,并填充其占位符)
4).进行查询得到ResultSet
5).利用ResultSet的getMetaData()方法获得ResultSetMetaData对象
6).处理ResultSet结果集
6.1).由ResultSetMetaData得到对象结果集中的列数
6.2).由ResultSetMetaData得到每一列的别名
6.3).由ResultSet得到具体每一列的值
7).创建一个Map,由上面的信息填充Map
8). 利用反射创建class对应的对象
9).遍历Map对象,利用反射为Class对象对应的属性赋值
10).关闭数据库资源
public <T> List<T> get(Class<T> clazz , String sql , Object ...args){
List<T> list =new ArrayList<>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1.获取Connection
connection = JDBCTool01.getConnection();
//2.获取PreparedStatement
preparedStatement = connection.prepareStatement(sql);
//3.填充占位符
for (int i = 0;i<args.length;i++){
preparedStatement.setObject(i+1,args[i]);
}
//4.进行查询得到ResultSet
resultSet = preparedStatement.executeQuery();
//5.若ResultSet非空,准备一个List<Map<String,Object>>:键:存放列的别名 值:存放列的值
//一个Map对应一个记录
List<Map<String,Object>> values = new ArrayList<>();
Map<String,Object> map = null;
//6.得到 ResultSetMetaData 对象
//ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
List<String> columnLabels = getColumnLabels(resultSet);
/*用自定义函数取得 columnLabels,则不用再获取ResultSetMetaData*/
while(resultSet.next()) {
map = new HashMap<>();
//7.处理ResultSet结果集
//8.由ResultSetMetaData
// 1).得到对象得到结果集中的列数
for (String columnLabel : columnLabels) {
// 2).得到每一列的别名
// String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
// 3).由ResultSet得到具体每一列的值
Object columnValue = resultSet.getObject(columnLabel);
//9.填充 Map 对象
map.put(columnLabel, columnValue);
}
//将得到的Map放入values
values.add(map);
}
//参数对应的Object对象
T bean =null;
//10.当List不为空,则遍历每一个Map对象,并转化为Class
if (values.size()>0){
for (Map<String ,Object> m : values){
bean = clazz.newInstance();
//11.遍历 Map 对象,用反射填充对象的属性值
for (Map.Entry<String,Object> entry : m.entrySet()){
String propertyName = entry.getKey();
Object value = entry.getValue();
ReflectionUtils.setField(bean.getClass(),propertyName,bean,value);
// BeanUtils.setProperty(bean,propertyName,value);
/*ReflectionUtils为反射工具类,和BeanUtils功能原理相同,利用反射填充对象*/
}
list.add(bean);
}
}
}catch (Exception e) {
e.printStackTrace();
}finally {
JDBCTool01.releaseDB2(connection,preparedStatement,resultSet);
}
return list;
}
/**
* 获取结果集的ColumnLabel
* @param resultSet
* @return
* @throws Exception
*/
private List<String> getColumnLabels(ResultSet resultSet)throws Exception{
List<String> labels = new ArrayList<>();
ResultSetMetaData resultSetMetaData =resultSet.getMetaData();
for (int i= 0 ; i<resultSetMetaData.getColumnCount();i++){
labels.add(resultSetMetaData.getColumnLabel(i+1));
}
return labels;
}
4.数据库的事务处理
4.1 开始事务(取消默认提交)
/**
* 开始事务
* @param connection
*/
public static void beginTx(Connection connection){
if(connection != null){
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4.2 提交事务(如果所有SQL语句都执行完则提交)
/**
* 提交事务
* @param connection
*/
public static void commit(Connection connection){
if(connection != null){
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4.3 回滚事务(如果出现异常则回滚事务)
/**
* 回滚事务
* @param connection
*/
public static void rollback(Connection connection){
if(connection != null){
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.批量处理数据库操作
批量处理事务即
1).先用PreparedStatement.addBatch()方法“积攒”SQL语句
2).“积攒”到目标值,统一执行一次PreparedStatement.executeBatch()
3).清空执行过的SQL语句PreparedStatement.clearBatch()
/*部分代码展示*/
//开始插入数据
for (int i = 0 ; i<9999;i++){
preparedStatement.setInt(1,i+1);
//积攒 SQL
preparedStatement.addBatch();
//积攒到指定数量,统一执行一次,并清空积攒的SQL语句
if((i+1)%300 == 0){ //执行条件
preparedStatement.executeBatch();
preparedStatement.clearBatch();
}
}
//若总条数不是指定数量的整倍数,则单独执行一次
if(10000%300 != 0 ){
preparedStatement.executeBatch();
preparedStatement.clearBatch();
}
6.BLOB(二进制大对象)
JDBC处理BLOB
1.增删改操作
String sql = "INSERT INTO SC VALUES(?,?,?,?)";
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBCTool01.getConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"q");
preparedStatement.setString(2,"p");
preparedStatement.setInt(3,123);
InputStream inputStream = new FileInputStream("p.jpg");
preparedStatement.setBlob(4,inputStream);
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCTool01.releaseDB2(connection,preparedStatement,null);
}
2.查询操作
String sql = "SELECT Sno,Cno,Grade,picture FROM SC WHERE Grade = 123 ";
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JDBCTool01.getConnection();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println(resultSet.getString(1));
Blob picture = resultSet.getBlob(4);
InputStream inputStream = picture.getBinaryStream();
OutputStream outputStream = new FileOutputStream("img1.jpg");
byte[] buffer = new byte[1024];
int len = 0;
while((len = inputStream.read(buffer)) != -1){
outputStream.write(buffer,0,len);
}
}
} catch (Exception e) {
e.printStackTrace();
}
7.关闭数据库资源
/**
* 关闭数据库资源
*/
public static void releaseDB(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
if (connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)