在前幾篇文章中,我對反射機制進行了詳細的介紹,並且使用反射手寫了一個SpringIOC框架。爲了鞏固和加深對反射機制的理解,本篇文章將使用反射封裝一個簡單的ORM框架。如果對反射不太熟悉的小夥伴,可以看我之前寫的幾篇文章【反射詳解】【使用反射手寫SpringIOC】,知識點非常齊全,相信看完以後,你一定會有所收穫,並且可以更好的理解本篇文章。
我們在做開發的過程中,需要經常對數據庫進行操作,這時我們就需要使用到ORM框架,例如比較常用的MyBatis和Hibernate。下面我將對ORM框架進行詳細的介紹並且封裝一個簡單的ORM框架。
1.什麼是ORM框架?
ORM,即0bject Relational Mapping (對象關係映射),它的作用是在關係型數據庫和業務實體對象之間作一個映射,這樣我們在具體的操作業務對象的時候,就不需要再去和複雜的SQL語句打交道,只需簡單的操作對象的屬性和方法即可。
簡單來講,就是通過類與數據庫表的映射關係,將對象持久化到數據庫中。
2.ORM框架的優點
當我們不使用ORM框架開發一個應用程序時,需要寫很多sql語句,每一次執行,都要打開/關閉數據連接,這樣在開發的過程是很麻煩的,而且開發效率低。並且像讀取、保存和刪除對象信息這些代碼都是重複的,會造成代碼冗餘。而使用ORM框架可以很好的解決這些問題,使我們減少很多繁瑣重複的工作量,讓我們的注意力集中在實現業務上。
ORM框架優點如下:
- 操作簡單,提高了開發效率;
- 減少重複代碼,消除冗餘;
- 數據訪問更抽象,更輕便;
- 支持面向對象封裝。
3.使用反射封裝ORM框架
下面我將使用反射機制封裝一個簡單的ORM框架來實現插入功能。
3.1創建數據庫表
首先需要創建一個數據庫表,下面我們就使用user表進行演示。
create table user(
userId varchar(20) PRIMARY KEY not null,
userName varchar(20) not null,
password varchar(20) not null,
emil varchar(20) not null
);
3.2創建實體類
接着我們需要創建user表所對應的實體類。
public class User {
public String userId;
public String userName;
public String password;
public String emil;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmil() {
return emil;
}
public void setEmil(String emil) {
this.emil = emil;
}
}
3.3使用反射進行封裝
使用反射把獲取屬性和屬性值的功能進行封裝,更有利於擴展。
public class DBUtils {
static final String JDBC_DRIVER="com.mysql.jdbc.Driver";
//數據庫連接地址,根據自己的實際情況就行修改
static final String DB_URL="jdbc:mysql://127.0.0.1:3306/orm?useUnicode=true&characterEncoding=utf-8&useSSL=false";
//用戶名和密碼,根據自己的實際情況就行修改
static final String USER="root";
static final String PASSWORD="root";
/**
* 連接數據庫
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
Connection connection=null;
try{
//1.加載驅動程序
Class.forName(JDBC_DRIVER);
//2.獲得數據庫鏈接
connection= DriverManager.getConnection(DB_URL, USER, PASSWORD);
System.out.println("數據庫連接成功!");
}catch (Exception e){
e.printStackTrace();
}
return connection;
}
/**
* 插入數據
* @return
* @param obj
*/
public static boolean insert(Object obj) throws Exception {
//1.獲取數據庫連接
Connection conn=getConnection();
//2.通過反射獲取類對象
Class cls = obj.getClass();
//3.獲取表名
String tableName=cls.getSimpleName();
//4.拼接sql語句
SQL sql = new SQL();
sql.INSERT_INTO(tableName);
sql.VALUES(Field(obj), FieldValue(obj));
String s=sql.toString();
//5.執行
Statement statement=conn.createStatement();
int result=statement.executeUpdate(s);
if(result!=0){
System.out.println("插入數據成功!");
return true;
}
return false;
}
/**
* 封裝當前類的所有屬性,拼接屬性sql
* @param obj
* @return
*/
public static String Field(Object obj) {
if (obj == null) {
return null;
}
// 獲取class文件
Class cls = obj.getClass();
// 獲取當前類所有屬性
Field[] Fields = cls.getDeclaredFields();
String fieldSql = getField(Fields);
return fieldSql ;
}
/**
* 獲取所有屬性並拼接成sql
* @param declaredFields
* @return
*/
public static String getField(Field[] declaredFields) {
StringBuffer sf = new StringBuffer();
for (int i = 0; i < declaredFields.length; i++) {
sf.append(declaredFields[i].getName());
if (i < declaredFields.length - 1) {
sf.append(",");
}
}
return sf.toString();
}
/**
* 封裝當前類的所有屬性值,拼接屬性值sql
* @param obj
* @return
*/
public static String FieldValue(Object obj) {
if (obj == null) {
return null;
}
// 獲取class文件
Class cls = obj.getClass();
// 獲取當前類的屬性值
Field[] Fields = cls.getDeclaredFields();
String fieldValueSql = getFieldValue(obj, Fields);
return fieldValueSql ;
}
/**
* 獲取所有屬性值並拼接成sql
* @param obj
* @param declaredFields
* @return
*/
public static String getFieldValue(Object obj, Field[] declaredFields) {
StringBuffer sf = new StringBuffer();
for (int i = 0; i < declaredFields.length; i++) {
// 獲取到屬性值
try {
Field field = declaredFields[i];
// 允許操作私有屬性
field.setAccessible(true);
// 獲取當前屬性的值
Object value = field.get(obj);
// 標識類型是否爲string類型
boolean flag = false;
if (value != null && (value instanceof String || value instanceof Timestamp)) {
flag = true;
}
//如果是String類型,則加上'',不是則不加
if (flag) {
sf.append("'"+value+"'");
} else {
sf.append(value);
}
if (i < declaredFields.length - 1) {
sf.append(",");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return sf.toString();
}
}
3.4效果演示
public class Test {
public static void main(String[] args) throws Exception {
User user=new User();
user.setUserId("000001");
user.setUserName("zhangsan");
user.setPassword("123456");
user.setEmil("[email protected]");
DBUtils.insert(user);
}
}
運行結果
數據庫user表
由運行結果可以看出,使用ORM框架插入數據成功。
我把源碼打包放在了百度雲網盤裏面,如果有需要的請自取【源碼地址】提取碼【c3at】