JDBC实现数据库的连接和操作:
一、连接数据库
1.Java代码
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* Java连接数据库 JDBC:
* 一、创建连接 Connection 对象
* 二、创建执行的语句 Statement 对象
* 三、执行 SQL 语句
*
* 一、创建连接
* 1.最耿直,直接创建对象。由于获取驱动的实例化对象时使用了第三方的包 mysql.jdbc.Driver()
* Driver driver = new com.mysql.jdbc.Driver();
*
* 2.法一不利于代码的移植和扩展性,所以在此基础之上,利用反射的方法创建 Driver 对象
* 获取类对象 getClassname()
* 获取构造器,创建对象 getDeclaredConstructor().newInstance()
* 获取指定的方法 getMethod(方法名,参数列表),如 getMethod("setPrice", int.class)
* 使用类的方法进行初始化 invoke(创建的对象, 14)
*
* Class clazz = Class.forName("com.mysql.jdbc.Driver");
* Driver driver = (Driver)clazz.getDeclaredConstructor().newInstance();
*
* 3.直接使用驱动不方便,引入驱动管理的实现类,进一步简化。并且在 mysql的Driver实现类中已经
* 声明了注册驱动
* Class.forName("com.mysql.jdbc.Driver");
* Connection conn = DriverManager.getConnection(url, user, password);
*
* 4.直接写死了用户名、密码等信息,不安全、不方便,引入配置文件
* 连接mysql,jdbc:mysql:协议,localhost:ip地址,3306:默认mysql的端口号,test:连接的数据库名称
* String string = "jdbc:mysql://localhost:3306/test";
* Properties info = new Properties();
* // 将用户名和密码封装在Properties中
* info.setProperty("user", "tom");
* info.setProperty("password", "123");
* 配置文件让用户能够脱离程序本身去修改相关的变量设置。
* 1、从目标路径 myjdbc.properites 中获取输入流对象
* 2、使用 Properties类的 load()方法从字节输入流中获取数据
* 3.使用 Properties类的 getProperty(String key)方法,根据参数key获取value
*
*
* 大白话讲解反射机制
* https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html
*
* 介绍配置文件
* https://www.cnblogs.com/gongchenglion/p/properties.html
*
* @Auther:sommer1111
* @date 2020/10/10 17:36
*/
public class _01_ConnectionMySQL {
public static void main(String[] args) throws Exception{
//1.从目标路径myjdbc.properites中获取输入流对象
InputStream in = _01_ConnectionMySQL.class.getClassLoader().getResourceAsStream("myjdbc.properties");
//2.使用Properties类的load()方法从字节输入流中获取数据
Properties pro = new Properties();
pro.load(in);
String driverClass = pro.getProperty("driverClass");
String url = pro.getProperty("url");
String name = pro.getProperty("user");
String password = pro.getProperty("password");
//3.加载驱动
Class.forName(driverClass);
//4.获取连接
Connection connect = DriverManager.getConnection(url,name,password);
System.out.println(connect);
}
}
2.配置文件myjdbc.properties
#设置配置信息
url=jdbc:mysql://localhost:3306/myemployees
user=tom
password=123
driverClass=com.mysql.jdbc.Driver
二、创建执行语句,Statement语句
将代码专门抽象成一个工具类
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* @Auther:sommer1111
* @date 2020/10/13 16:25
*/
public class statementUtil {
//获取连接
public static Connection getConnect() throws Exception {
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
Properties ps = new Properties();
ps.load(in);
String driverClass = ps.getProperty("driverClass");
String url = ps.getProperty("url");
String user = ps.getProperty("user");
String password = ps.getProperty("password");
Class.forName(driverClass);
return DriverManager.getConnection(url, user, password);
}
//关闭资源
public static void closeConnetion(Connection con,PreparedStatement sta){
try {
if(con != null){
con.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(sta != null){
sta.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//增加一个关闭资源
public static void closeConnetion(Connection con, PreparedStatement sta, ResultSet rs){
try {
if(con != null){
con.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(sta != null){
sta.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(rs != null){
rs.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//设置statment
public static void update(String sql,Object ...args) {
Connection connection = null;
PreparedStatement statement = null;
try {
//1.预编译
connection = getConnect();
statement = connection.prepareStatement(sql);
//2.填充占位符
for(int i = 0;i<args.length;i++){
statement.setObject(i+1,args[i]);
}
//3.执行
statement.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
closeConnetion(connection,statement);
}
}
}
三、执行SQL语句
1.实现数据库的操作:增删改
,此时并没有返回值
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
/**
* 实现创建数据库语句的操作(增删改,没有返回)
*
* 1.获取数据库连接
* InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
* Properties ps = new Properties();
* ps.load(in);
* String driverClass = ps.getProperty("driverClass");
* String url = ps.getProperty("url");
* String user = ps.getProperty("user");
* String password = ps.getProperty("password");
* Class.forName(driverClass);
* connection = DriverManager.getConnection(url, user, password);
*
* 2.预编译sql语句,返回PreparedStatement的实例
* String sql = new String("UPDATE locations SET street_address = ? WHERE location_id = ?;");
* statement = connection.prepareStatement(sql);
*
* 3.填充占位符
* statement.setObject(1,"wuhan");
* statement.setObject(2,"2200");
* 4.执行
* statement.execute();
* 5.资源的关闭(都需要用 try catch)
* statement.close();
* connection.close()
*
* 优化:
* 1.将数据库的连接、预编译、关闭资源都封装成方法 statementUtil,简化代码
*
* @Auther:sommer1111
* @date 2020/10/13 15:38
*/
public class _02_Statement {
public static void main(String[] args) {
String sql = "UPDATE locations SET street_address = ? WHERE location_id = ?;";
Object[] arg = {"jiangxi","2300"};
statementUtil.update(sql,arg);
// Connection connection = null;
// PreparedStatement statement = null;
// try {
// //1.获取数据库连接
// InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
// Properties ps = new Properties();
// ps.load(in);
// String driverClass = ps.getProperty("driverClass");
// String url = ps.getProperty("url");
// String user = ps.getProperty("user");
// String password = ps.getProperty("password");
// Class.forName(driverClass);
// connection = DriverManager.getConnection(url, user, password);
//
//
// //2.预编译sql语句,返回PreparedStatement的实例
// String sql = new String("UPDATE locations SET street_address = ? WHERE location_id = ?;");
// statement = connection.prepareStatement(sql);
// //3.填充占位符
// statement.setObject(1,"wuhan");
// statement.setObject(2,"2200");
//
// //4.执行
// statement.execute();
// } catch (Exception e) {
// e.printStackTrace();
// }finally {
// //5.资源的关闭
// if(statement != null){
// try {
// statement.close();
// } catch (SQLException throwables) {
// throwables.printStackTrace();
// }
// }
// if(connection != null){
// try {
// connection.close();
// } catch (SQLException throwables) {
// throwables.printStackTrace();
// }
// }
// }
}
}
2.实现数据库的操作:查
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
/**
* JDBC 实现数据库的查询
* 一、分析:
* 1. 使用 PreparedStatement实现查询操作,查询操作的区别在于会有一个数据返回
* 2. 返回的数据用一个类封装 ResultSet,这个表中只有数据,但是如果我们还需要获取表头信息
* 3. 用 getMetaData 获取关于 ResultSet 对象中列的类型和属性信息的对象 ResultSetMetaData
* 4. ResultSet 资源也需要释放
*
* 二、实现:
* 1.获取连接
* 2.执行sql语句,得打结果返回 ResultSet,ResultSet rs = ps.executeQuery();
* 3.要想显示结果,将数据读取出来封装在一个 Collection 对象中 key-value 键值对
* |--读取出表头信息:
* (1)获取元数据集,ResultSetMetaData rsmd = rs.getMetaData();
* (2)获取结果集中的列数,迭代读取元数据集的表头:
* int columnCount = rsmd.getColumnCount();
* String columnName = rsmd.getColumnName(i + 1);
* (3)获取列值,此时列值属性失去,都变成了 Object
* Object columValue = rs.getObject(i + 1);
* (4)利用反射恢复列值在 Collection 对象的属性,并添加到集合中:
* Field field = Customer.class.getDeclaredField(columnLabel);
* field.setAccessible(true);使在用反射时能访问私有变量
* field.set(cust, columValue);
* 4.关闭资源
*
* 三、笔记
* 1.查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象
* ResultSet通过指针迭代取数据,常用方法有:
* next(),用于迭代的指针,指向下一个值。
* getObject(),获取列值。
*
* 2.ResultSetMetaData对象的常用方法
* getColumnName(int column):获取指定列的名称
* getColumnLabel(int column):获取指定列的别名(MySQL中的别名,推荐使用)
* getColumnCount():返回当前 ResultSet 对象中的列数。
* getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
*
* @Auther:sommer1111
* @date 2020/10/14 15:35
*/
public class _03_StatementQuery {
public static void main(String[] args) {
String sql = "SELECT employee_id,last_name,email,salary FROM employees WHERE employee_id>?;";
Collection<Employees> employees = queryForEmployees(sql, 128);
for(Employees employee:employees){
System.out.println(employee);
}
}
//基本实现
public static Collection<Employees> queryForEmployees(String sql, Object...args) {
statementUtil util = null;
Connection connect = null;
PreparedStatement ps = null;
ResultSet rs = null;
Collection<Employees> list = new ArrayList<>();
try {
util = new statementUtil();
connect = util.getConnect();
ps = connect.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
//得到数据集
rs = ps.executeQuery();
//获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//开始读取值
while(rs.next()){//一行的数据为一个next
Employees em = new Employees();
int columnCount = rsmd.getColumnCount();
for (int i = 0; i < columnCount; i++) {
//获取数据
Object value = rs.getObject(i+1);
//获取列名,最好使用别名来获取
String columnName = rsmd.getColumnLabel(i + 1);
//恢复属性
Field field = Employees.class.getDeclaredField(columnName);
field.setAccessible(true);
field.set(em,value);
}
list.add(em);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally{
util.closeConnetion(connect,ps,rs);
}
return null;
}
//优化增强扩展性,将具体的类换成泛型
public static <T>T queryForEmployees(Class<T> clazz,String sql, Object...args) throws Exception {
//修改创建类的语句
T t = clazz.getDeclaredConstructor().newInstance();
//修改反射设值的语句,其余不变
//field.set(t,value);
return null;
}
}
3.用到的Employees类
/**
* @Auther:sommer1111
* @date 2020/10/14 16:28
*/
class Employees {
private int employee_id;
private String last_name;
private String email;
private double salary;
public Employees() {
}
public Employees(int employee_id, String last_name, String email, int salary) {
this.employee_id = employee_id;
this.last_name = last_name;
this.email = email;
this.salary = salary;
}
@Override
public String toString() {
return "Employees{" +
"employee_id=" + employee_id +
", last_name='" + last_name + '\'' +
", email='" + email + '\'' +
", salary=" + salary +
'}';
}
public int getEmployee_id() {
return employee_id;
}
public void setEmployee_id(int employee_id) {
this.employee_id = employee_id;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}