前言
Mysql 8.0提示:以下是本篇文章正文内容,下面案例可供参考
一、数据库的连接
- 读取配置文件中的4个基本信息
1.1 加载配置文件
通过getClassLoader()获取该字节码文件对应的类加载器,并获取指定文件的一个字节流 InputStream
1.2 创建Properties对象,load() 方法加在配置文件,读取配置信息 - 加载驱动
- 获取连接
准备配置文件 jdbc.properties,此配置文件放在工程目录下
# 数据库连接的4个基本要素(user,password,url,driverClasss)
user=root
password=aa1234
# 以下是mysql 8 的连接方式
url=jdbc:mysql://localhost/student?serverTimezone=UTC
driverClass=com.mysql.cj.jdbc.Driver
# 以下是mysql 5 的连接方式
#url=jdbc:mysql://localhost:3306/student?rewriteBatchedStatements=true
#driverClass=com.mysql.jdbc.Driver
测试:
import org.junit.Test;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
/**
* 数据库的连接
* @Author: junxiang
*/
public class ConnectionTest {
// 将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
/*
* 此种方式的好处:
* 1.实现了数据与代码的分离。实现了解耦
* 2.如果需要修改配置文件信息,可以避免程序重新打包。
*/
@Test
public void getConnection() throws Exception{
//1.读取配置文件中的4个基本信息
// 1.1 加载配置文件
// getClassLoader()获取该字节码文件对应的类加载器,方便加载进内存
// 获取指定文件的一个字节流 InputStream
ClassLoader classLoader = ConnectionTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("jdbc.properties");
// 创建Properties对象
// load() 方法加在配置文件,传进去一个 InputStream/inStream/Reader/reader 对象
Properties pros = new Properties();
pros.load(is);
// 1.2 读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//2.加载驱动
Class.forName(driverClass);
//3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
}
二、数据库的CRUD(增删改查)
创建customers表
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(15) DEFAULT NULL,
`email` varchar(20) DEFAULT NULL,
`birth` date DEFAULT NULL,
`photo` mediumblob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=gb2312;
创建Customer类与数据库中表customers对应
import java.sql.Date;
/*
* ORM编程思想 (object relational mapping)
* 一个数据表对应一个java类
* 表中的一条记录对应java类的一个对象
* 表中的一个字段对应java类的一个属性
*
*/
public class Customer {
private int id;
private String name;
private String email;
private Date birth;
public Customer() {
super();
}
public Customer(int id, String name, String email, Date birth) {
super();
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", birth=" + birth + "]";
}
}

创建工具类
工具类封装了数据库的连接与资源的释放方法
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
*
* @Description 操作数据库的工具类
* @Author: junxiang
*
*/
public class JDBCUtils {
/**
*
* @Description 获取数据库的连接
* @Author: junxiang
* @return Connection
* @throws Exception
*/
public static Connection getConnection() throws Exception {
// 1.读取配置文件中的4个基本信息
ClassLoader classLoader = ConnectionTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/**
*
* @Description 关闭连接和Statement的操作
* @Author: junxiang
* @param conn
* @param ps
*/
public static void closeResource(Connection conn,PreparedStatement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
*
* @Description 关闭资源操作
* @Author: junxiang
* @Date: 2021/3/08 19:39
* @param conn Connection 对象
* @param ps PreparedStatement 对象
* @param rs ResultSet 对象(结果集)
*/
public static void closeResource(Connection conn,PreparedStatement ps,ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
通用的增删改方法
- 获取数据库的连接
- 预编译sql语句,返回PreparedStatement的实例
- 填充占位符
- 执行SQL操作
- 释放资源
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Properties;
import jdbc.preparedstatement.util.JDBCUtils;
import org.junit.Test;
/**
*
* @Description
* 使用PreparedStatement来替换Statement,实现对数据表的增删改操作
* @Author: junxiang
*
*/
public class PreparedStatementUpdateTest {
@Test
public void testCommonUpdate(){
// insert
// String sql = "insert into customers(name,email,birth) values(?,?,?)"; // ? -> 占位符
// int oper = update(sql, "李四", "lisi@126.com", "1999-09-10");
// update
// String sql = "update customers set email = ? where id = ?";
// int oper = update(sql, "lisi@qq.com", "27");
// delete
String sql = "delete from customers where id = ?";
int oper = update(sql, 27);
if(oper > 0 ){
System.out.println("操作成功!");
}else {
System.out.println("操作失败!");
}
}
/**
* 通用的增删改操作
* @param sql
* @param args
* @return
*/
//sql中占位符的个数与可变形参的长度相同!
public int update(String sql,Object ...args){
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
// 预编译已经把sql的逻辑给确定,之后填充的占位符(?,?,?)只认为是数据
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i = 0;i < args.length;i++){
/*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x the object containing the input parameter value
*/
ps.setObject(i + 1, args[i]);//小心参数声明错误!!
}
//4.执行
/*
* ps.execute():
* 如果执行的是查询操作,有返回结果,则此方法返回true;
* 如果执行的是增、删、改操作,没有返回结果,则此方法返回false.
*/
//方式一:
// return ps.execute();
//方式二:int executeUpdate()
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
return 0;
}
}
通用的查方法
- 获取数据库的连接
- 预编译sql语句,返回PreparedStatement的实例
- 填充占位符
- 执行SQL操作,获取结果集
rs = ps.executeQuery(); - 通过结果集获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData(); - 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount(); - 读取并处理数据库中数据,封装成对应的类对象 t
7.1 理结果集一行数据中的每一个列
7.2 获取列值及每个列的列名
7.3 通过反射,给t对象指定的columnName属性,赋值为columValue - 打印查询结果
- 释放资源
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import jdbc.preparedstatement.bean.Customer;
import jdbc.preparedstatement.bean.Order;
import jdbc.preparedstatement.util.JDBCUtils;
import org.junit.Test;
/**
*
* @Description 数据库通用的 查: 查询不同表的数据
* @Author: junxiang
*
*/
public class PreparedStatementQueryTest {
@Test
public void testGetForList(){
String sql = "select id,name,email from customers where id < ?";
List<Customer> list = getForList(Customer.class,sql,12);
list.forEach(System.out::println);
String sql1 = "select order_id orderId,order_name orderName from `order`";
List<Order> orderList = getForList(Order.class, sql1);
orderList.forEach(System.out::println);
}
/**
* 定义泛型方法
* @param clazz
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> List<T> getForList(Class<T> clazz,String sql, Object... args){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
//创建集合对象
ArrayList<T> list = new ArrayList<T>();
while (rs.next()) {
// 方式1:通过Class 对象 t 中的newInstance() 直接创建对象
T t = clazz.newInstance();
// 方式2:先获取构造器,然后再创建对象
// T t1 = clazz.getConstructor().newInstance();
// T t2 = clazz.getDeclaredConstructor().newInstance();
// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
// 获取每个列的列名或别名
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
// 将每个 对象加入到List中
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
}
总结
- 本文使用
读取配置文件方式连接Mysql,并用一个Java类对表进行映射,将表的字段封装成类的属性:
1.1 一个数据表对应一个java类
1.2 表中的一条记录对应java类的一个对象
1.3 表中的一个字段对应java类的一个属性 - 用Statement 的子接口
PreparedStatement 接口来操作数据表,即调用 Connection 对象的preparedStatement(String sql)方法获取 PreparedStatement 对象,它表示一条预编译过的 SQL 语句,用占位符?来表示SQL 语句中的参数,setXxx()方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的SQL 语句中的参数的值,第二个参数可以是一个可变长参数 - 用ResultSetMetaData获取关于 ResultSet 对象中列的类型和属性信息的对象(
即获取结果集的元数据:ResultSetMetaData),ResultSetMetaData rsmd= rs.getMetaData() - 运用了Java反射的知识
4.1 在读取配置文件中使用getClassLoader()获取该字节码文件对应的类加载器,从而获取指定文件的一个字节流 InputStream
4.2 在查的操作时,通过Class 对象 t 中的newInstance() 直接创建对象(也可以先获取构造器,在创建对象)
4.3 当获取到数据库中列名及列值时,通过类对象的方法getDeclaredField()获取类的属性,并调用set()方法给刚刚获取到的属性赋值
本文详细介绍如何使用Java进行数据库连接及增删改查操作,包括配置文件读取、PreparedStatement使用、结果集处理等关键技术。
369

被折叠的 条评论
为什么被折叠?



