前言
当你项目不考虑并发、高性能、追求更快的开发效率,业务只涉及单表时推荐使用该方法(不写重复代码)
关于JDBC操作数据库主要分享两点
- 【图+说】JDBC-数据库连接
- 【JDBC工具类】对数据库 CRUD(增、删、改、查)封装可通用方法
JDBC操作数据库步骤
- 导入jar包,加载驱动
- 获取连接Connection
- 获取执行SQL语句的对象PreparedStatement
- 执行增删改查操作
- 解析查询结果ResultSet
- 关闭释放资源
1,2.3在JDBC--数据库连接讲解说明
3,4,5在对数据库CRUD(增、删、改、查)封装可通用方法中实战说说明具体操作
一.JDBC--数据库连接
1.1.1导入MySQL数据库驱动jar包 mysql-connector-java-xxx.jar(xxx是驱动的版本)
1.1.2【maven项目】MySQL数据库驱动依赖写法(pom.xml中加入,这里我用的是5.1.22驱动版本)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.22</version>
</dependency>
1.2.加载MySQL驱动,核心代码Class.forName("com.mysql.jdbc.Driver");
此处可能会抛出java.lang.ClassNotFoundException: com.mysql.jdbc.Driver异常,抛出该异常的原因就是未正确导入jar包
static {
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
2.获取和MySQL的连接,获取连接时需要提供待连接的数据库的url、用户名和密码
private static String url = "jdbc:mysql://localhost:3306/数据库名?useSSL=true&useUnicode=true&characterEncoding=UTF-8"
private static String username = "数据库用户名";
private static String password = "数据库密码";
//获取数据库连接
public static Connection getConection(){
Connection con = null ;
try {
con = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return con ;
}
6关闭数据库资源
注意是先关闭结果集(ResultSet),再关闭语句(PreparedStatement),最后关闭连接(Connection)。
原因:如果connection关闭了,后面Statement和ResultSet相关的操作就会受到影响。所以平时一定要注意关闭资源的先后顺序,先关闭ResultSet,然后是Statement,最后是Connetion,刚好与创建相应对象时的顺序相反。
public static void closeAll(AutoCloseable...ables){
for (AutoCloseable able : ables) {
if(able!=null){
try {
able.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
二、【JDBC工具类】对数据库 CRUD(增、删、改、查)封装可通用方法
CRUD通用方法局限性
- 实体类名字必须和表名一致
- 安全性低(暴漏字段名)
- 灵活性低(通用和灵活永远的矛盾体)
- Update操作时会全表更新
- Select操作会全字段查询
这里直接上代码解说了,里面一行一注释!!不懂最后留言互动!!
CRUD(增、删、改、查)代码【可直接使用,亲测有效】
声明:Object...obj为可变数组参数,传参数时可传可不传,效果类似Object[] obj
调用时什么都没有传,那么Object[]的长度就是0。传的时候传了几个,Object[]的长度就是几,下标获取对应传参值
public boolean CUD(String sql , Object...obj){}
- 参数1:要执行的sql语句(insert/update/delete)
- 参数2:要注入的参数值与sql中?对应的参数
public <T> List<T> Query(String sql, Class<T> clazz, Object...obj)
- 参数1:要执行查询的的sql语句(select)
- 参数2:反射获取Class实例对象(三种方式:类名.class/new 类名().getClass/Clas.forName(全限定类名))
- 参数3要注入的参数值与sql中?对应的参数
package com.cxl.jdbcutils;
import java.awt.image.RasterFormatException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author 萌小崔
* @version 1.0
* @description: JDBC工具类
* @date 2021/11/2 16:48
*/
public class JDBCUtils {
private String url = null;
private String username = null;
private String password = null;
//初始化工具类 连接数据库 参数1:url 参数2:数据库用户名 参数3:数据库用户密码
public JDBCUtils(String url,String username,String password) {
this.url = url;
this.username = username;
this.password = password;
}
//加载驱动
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//连接数据库
public Connection getConnection(){
Connection con = null ;
try {
con = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
//释放资源
public void closeresource(AutoCloseable...ables){
for (AutoCloseable able : ables) {
if(able!=null){
try {
able.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//增删改通用方法
public boolean CUD(String sql , Object...obj){
//连接数据库
Connection con = getConnection();
PreparedStatement pstmt = null ;
try {
//获取预编译对象
pstmt = con.prepareStatement(sql);
//获取预编译对象元数据
ParameterMetaData pmd = pstmt.getParameterMetaData();
//获取元数据参数个数
int parameterCount = pmd.getParameterCount();
//判断参数个数同占位符数量是否一致
if(parameterCount!=obj.length){
//不一致
throw new RasterFormatException("占位符同参数个数不等");
}else{
for (int i = 0; i < obj.length; i++) {
//一致 将其赋值 顺序必须一致
pstmt.setObject(i+1, obj[i]);
}
int executeUpdate = pstmt.executeUpdate();
return executeUpdate>0;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关流
closeresource(pstmt,con);
}
return false;
}
//查询通用方法
public <T> List<T> Query(String sql, Class<T> clazz, Object...obj){
//T Student 泛型方法 List<T> 实现List接口泛型集合,
ArrayList<T> list = new ArrayList();
Connection con = getConnection();
PreparedStatement ps = null ;
ResultSet rs=null;
try {
//获取sql的预编译对象
ps = con.prepareStatement(sql);
//获取该对象的元数据
ParameterMetaData pmd = ps.getParameterMetaData();
//获取数据中的参数个数 也就是占位符的个数
int parameterCount = pmd.getParameterCount();
//判断占位符个数同参入个数是否相等
if(parameterCount!=obj.length){
//不相等报错提示
throw new RasterFormatException("占位符数同参数数量不等");
}else{
//相等情况下将传入参数赋值给sql语句
for(int i=0;i<obj.length;i++){
ps.setObject(i+1, obj[i]);
}
//执行sql语句
rs = ps.executeQuery();//查询 返回ResultSet 结果集rs
//获取结果集的元数据
ResultSetMetaData metaData = rs.getMetaData();
//获取列名数量
int columnCount = metaData.getColumnCount();
while(rs.next()){
//反射创建对象 无参构造
T bean = clazz.newInstance();
for(int i=1;i<=columnCount;i++){
//获取列名 (字段名在同一列 从1开始 往下)
//获取列名 时 数据库 + 别名 (同实体类对应)
String catalogName = metaData.getColumnName(i);
//通过列名获取对应的值
Object object = rs.getObject(catalogName);
//通过反射 获取 列名的 set get 方法 比如 你的eid
// (PropertyDescriptor下面有解释)
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(catalogName, clazz);
//调用写入属性值得方法
Method writeMethod = propertyDescriptor.getWriteMethod();
//调用方法 给其赋值
writeMethod.invoke(bean, object);
}
/*
思路:rs 是你查询到的结果集
循环遍历rs while里主要执行是创建你传入的对象 将其赋值 然后加到list中去
*/
list.add(bean);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
closeresource(rs,ps,con); //先关闭结果集(ResultSet),再关闭语句(PreparedStatement),最后关闭连接(Connection)
}
return list;
}
}
【解释】查询方法中PropertyDescriptor 类表示 JavaBean 类通过存储器导出一个属性。
构造方法有:
PropertyDescriptor(String propertyName, Class<?> beanClass)
PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName)
PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
常用方法有:
Class<?> getPropertyType() // 获取属性的java类型对象
Method getReadMethod() // 获得用于读取属性值的方法
Method getWriteMethod() // 获得用于写入属性值的方法
【实战】CRUD封装方法的使用教程
如上所说的该方法有一定的局限性,主要一点实体类名字必须和表名一致
数据库/实体类
测试类
public class MyTest {
public static void main(String[] args) {
//初始化工具类 连接数据库 参数1:url 参数2:数据库用户名 参数3:数据库用户密码
JDBCUtils jdbc = new JDBCUtils("jdbc:mysql://localhost:3306/zg2cvs?useUnicode=true&characterEncoding=utf-8", "root", "123456");
List<Waipai> byLIst = jdbc.findByLIst("select * from waipai", Waipai.class);
for (Waipai waipai : byLIst) {
System.out.println(waipai);
}
}
}
测试效果:
到此JDBC操作数据库讲解就结束了!有疑问尽可留言互动!!!!
Thanks!1