簡(jiǎn)易JDBC框架實(shí)現(xiàn)過(guò)程詳解
1 準(zhǔn)備
- JDBC 基本知識(shí)
- JDBC元數(shù)據(jù)知識(shí)
- 反射基本知識(shí)
2: 兩個(gè)問(wèn)題
業(yè)務(wù)背景:系統(tǒng)中所有實(shí)體對(duì)象都涉及到基本的CRUD操作。所有實(shí)體的CUD操作代碼基本相同,僅僅是發(fā)送給數(shù)據(jù)庫(kù)的sql語(yǔ)句不同而已,因此可以把CUD操作的所有相同代碼抽取到工具類(lèi)的一個(gè)update方法中,并定義參數(shù)接收變化的sql語(yǔ)句。
實(shí)體的R操作,除sql語(yǔ)句不同之外,根據(jù)操作的實(shí)體不同,對(duì)ResultSet的映射也各不相同,因此可定義一個(gè)query方法,除以參數(shù)形式接收變化的sql語(yǔ)句外,可以使用策略模式由query方法的調(diào)用者決定如何把ResultSet中的數(shù)據(jù)映射到實(shí)體對(duì)象中。
3: JDBC 封裝 update query方法
public class JdbcNewUtils {
private JdbcNewUtils() {}
/**
* 這里可以使用properties進(jìn)行替換
*/
private static final String USER = "root";
private static final String PWD = "root";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/day?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&generateSimpleParameterMetadata=true";
private static final String DRIVER= "com.mysql.jdbc.Driver";
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
Connection connection = DriverManager.getConnection(URL, USER, PWD);
return connection;
}
/**
* CUD 返回影響數(shù)目
* @param sql
* @param args
* @return int
*/
public static int update(String sql,Object [] args) {
PreparedStatement ps = null;
Connection conn = null;
try {
conn=getConnection();
ps = conn.prepareStatement(sql);
for (int i = 1; i <= args.length; i++) {
ps.setObject(i, args[i-1]);
}
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn, ps);
}
return 0;
}
/**
* 查詢結(jié)果封裝Bean
* @param sql
* @param args
* @param rsh
* @return Object
*/
public static Object query(String sql,Object [] args,ResultSetHandler rsh) {
PreparedStatement ps = null;
Connection conn = null;
try {
conn=getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1, args[i]);
}
return rsh.handle(ps.executeQuery());
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn, ps);
}
return null;
}
/**
* 關(guān)閉所有打開(kāi)的資源
*/
public static void close(Connection conn, Statement stmt) {
if(stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 關(guān)閉所有打開(kāi)的資源
*/
public static void close(Connection conn, Statement stmt, ResultSet rs) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
close(conn, stmt);
}
}
4: query
每次查詢根據(jù)查詢的參數(shù)不同, 返回的ResultSet 也不同, 這個(gè)規(guī)則我們需要單獨(dú)編寫(xiě)規(guī)則解析器, 這里用到了策略設(shè)計(jì)模式,
將ResultSetHandler 定義解決問(wèn)題的接口, handle為那些需要實(shí)現(xiàn)的具體解決的辦法
public interface ResultSetHandler {
Object handle(ResultSet resultSet);
}
下面我實(shí)現(xiàn)了Beanhandler 和 BeanListHandler 分別是 單個(gè)的Bean 和一個(gè)列表的Bean
package jdbc.simpleframwork;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class BeanHandler implements ResultSetHandler {
private Class<?> obj;
public BeanHandler(Class<?> obj) {
this.obj = obj;
}
@Override
public Object handle(ResultSet resultSet){
try {
if(!resultSet.next()) {
return null;
}
Object instance = obj.newInstance();
ResultSetMetaData metaData = resultSet.getMetaData();
int count = metaData.getColumnCount();
for(int i=1;i<=count;i++) {
Field f = obj.getDeclaredField(metaData.getColumnName(i));
f.setAccessible(true);
f.set(instance, resultSet.getObject(i));
}
return instance;
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}
}
package jdbc.simpleframwork;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
public class BeanListHandler implements ResultSetHandler {
private Class<?> clazz;
public BeanListHandler(Class<?> clazz) {
super();
this.clazz = clazz;
}
@Override
public Object handle(ResultSet resultSet) {
try {
ArrayList<Object> objlist = new ArrayList<>();
ResultSetMetaData metaData = resultSet.getMetaData();
int count = metaData.getColumnCount();
while (resultSet.next()) {
Object instace = clazz.newInstance();
for (int i = 0; i < count; i++) {
Field f = clazz.getDeclaredField(metaData.getColumnName(i + 1));
f.setAccessible(true);
f.set(instace, resultSet.getObject(i + 1));
f.setAccessible(false);
}
objlist.add(instace);
}
return objlist;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
5 測(cè)試
public class TestFramwork {
public static void main(String[] args) throws SQLException {
Connection conn = JdbcNewUtils.getConnection();
String sql = "select * from student where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
Student stu = (Student) JdbcNewUtils.query(sql, new Object[] { 1 }, new BeanHandler(Student.class));
System.out.println(stu);
String sql2 = "select * from student";
ArrayList<Student> list = (ArrayList<Student>) JdbcNewUtils.query(sql2, new Object[] {},
new BeanListHandler(Student.class));
System.out.println(list);
}
}
6: 總結(jié)
Update系列操作:
對(duì)于CUD操作,SQL只有站位符號(hào)的多少發(fā)生了改變,對(duì)于傳遞參數(shù)才是我們需要關(guān)注的地方,但是JDBC提供了一系列傳遞參數(shù)解析的辦法,通過(guò)set系列函數(shù),將參數(shù)值傳遞進(jìn)行,所以我們只需要封裝一個(gè)通用的update即可
Query系列操作
對(duì)R操作,就復(fù)雜得多,SQL語(yǔ)句的不同,返回的ResultSet也不同,可以單個(gè)Bean 或者一個(gè)List,一個(gè)Map等,可以看出來(lái),實(shí)際上很多框架提供的也就是這些方法的封裝
對(duì)了 真正應(yīng)用上 我們的DAO 一邊是 下面的寫(xiě)法
public class AccountDao {
public void add(Account account) throws SQLException{
String sql = "insert into account(name , money) values(?, ?)";
Object[] params = {account.getName(), account.getMoney()};
JdbcUtils.update(sql, params);
}
public void delete(int id ) throws SQLException{
String sql = "delete from account where id = ?";
Object[] params = {id};
JdbcUtils.update(sql, params);
}
public void update(Account account) throws SQLException{
String sql = "update account set name = ?, money = ? where id = ?";
Object params[] = {account.getName(), account.getMoney(), account.getId()};
JdbcUtils.update(sql, params);
}
public Account find(int id ) throws SQLException{
String sql = "select * from account where id = ?";
Object params[] = {id};
return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account.class));
}
public List getAll() throws SQLException{
String sql = "select * from account";
Object params[] = {};
return (List)JdbcUtils.query(sql, params, new BeanListHandler(Account.class));
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java使用JDBC或MyBatis框架向Oracle中插入XMLType數(shù)據(jù)
- 在Java的Spring框架的程序中使用JDBC API操作數(shù)據(jù)庫(kù)
- java數(shù)據(jù)庫(kù)開(kāi)發(fā)之JDBC的完整封裝兼容多種數(shù)據(jù)庫(kù)
- java開(kāi)發(fā)之Jdbc分頁(yè)源碼詳解
- Java基礎(chǔ)開(kāi)發(fā)之JDBC操作數(shù)據(jù)庫(kù)增刪改查,分頁(yè)查詢實(shí)例詳解
- 5分鐘快速學(xué)會(huì)spring boot整合JdbcTemplate的方法
- JDBC連接MySQL數(shù)據(jù)庫(kù)批量插入數(shù)據(jù)過(guò)程詳解
相關(guān)文章
SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)
隨著系統(tǒng)和業(yè)務(wù)的不停升級(jí),前后端代碼放在一起的項(xiàng)目越來(lái)越臃腫,已經(jīng)無(wú)法快速迭代和職責(zé)區(qū)分了,于是紛紛投入了前后端分離的懷抱,發(fā)現(xiàn)代碼和職責(zé)分離以后,開(kāi)發(fā)效率越來(lái)越高了,但是以前的驗(yàn)證碼登錄方案就要更改了。本文來(lái)看一下SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)2021-05-05
Java?NIO下ByteBuffer的常用方法學(xué)習(xí)
這篇文章主要帶大家來(lái)初步學(xué)習(xí)一下NIO?中的?ByteBuffer的應(yīng)用與常用方法,文中的示例代碼講解詳細(xì),對(duì)我們深入學(xué)習(xí)Java有一定的幫助,感興趣的可以了解一下2023-05-05
Java通過(guò)調(diào)用FFMPEG獲取視頻時(shí)長(zhǎng)
這篇文章主要為大家詳細(xì)介紹了Java通過(guò)調(diào)用FFMPEG獲取視頻時(shí)長(zhǎng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
Spring data elasticsearch使用方法詳解
這篇文章主要介紹了Spring data elasticsearch使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Java class文件格式之?dāng)?shù)據(jù)類(lèi)型(二)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java class文件格式之?dāng)?shù)據(jù)類(lèi)型(二)的相關(guān)資料,需要的朋友可以參考下2017-06-06
使用mybatis-plus的insert方法遇到的問(wèn)題及解決方法(添加時(shí)id值不存在異常)
這篇文章主要介紹了使用mybatis-plus的insert方法遇到的問(wèn)題及解決方法(添加時(shí)id值不存在異常),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08

