简单ORM映射方案(JDBC)
代码
package orm.factory;
import orm.annotation.TableColumn;
import orm.handler.TableColumnGetter;
import orm.handler.TableHandler;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.*;
public class TableObjectFactory {
private static final String STRING = "java.lang.String";
private static final String INTEGER = "java.lang.Integer";
private static final String DOUBLE = "java.lang.Double";
private static final String CHARACTER = "java.lang.Character";
private static final String BOOLEAN = "java.lang.Boolean";
private static final String SHORT = "java.lang.Short";
private static final String BYTE = "java.lang.Byte";
private static final String LONG = "java.lang.Long";
private static final String FLOAT = "java.lang.Float";
private static final String DATE = "java.util.Date";
private static final Map<String,Class> TYPE_MAP = new HashMap<>();
private static final Map<String,String> METHOD_MAP = new HashMap<>();
static {
TYPE_MAP.put(STRING,String.class);
TYPE_MAP.put(INTEGER,Integer.class);
TYPE_MAP.put(DOUBLE,Double.class);
TYPE_MAP.put(BOOLEAN,Boolean.class);
TYPE_MAP.put(SHORT,Short.class);
TYPE_MAP.put(BYTE,Byte.class);
TYPE_MAP.put(LONG,Long.class);
TYPE_MAP.put(FLOAT,Float.class);
TYPE_MAP.put(DATE, Date.class);
METHOD_MAP.put(STRING,"String");
METHOD_MAP.put(INTEGER,"Int");
METHOD_MAP.put(DOUBLE,"Double");
METHOD_MAP.put(BOOLEAN,"Boolean");
METHOD_MAP.put(SHORT,"Short");
METHOD_MAP.put(BYTE,"Byte");
METHOD_MAP.put(LONG,"Long");
METHOD_MAP.put(FLOAT,"Float");
METHOD_MAP.put(DATE,"Date");
}
/**
* 自动解析result为对应持久对象数组
* @param resultSet 结果集
* @param tClass 持久对象字节码
* @param <T> 持久对象泛型
* @return
*/
public static <T>List<T> toObjectList(ResultSet resultSet, Class<T> tClass){
List<TableColumnGetter> tableColumnGetterList = new ArrayList<>();
Class tableClass = tClass;
//获取属性标注的字段值,自动解析字段
Field[] fields = tableClass.getDeclaredFields();
if (tableClass == null){
return new ArrayList<>();
}
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null){
//获取属性名
String propertyName = field.getName();
//set函数名
String setMethodName = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
//字段名
String columnLabel = tableColumn.value();
//获取属性类型
String typeName = field.getGenericType().getTypeName();
try {
//获取到类型字节码
Class typeClass = TYPE_MAP.get(typeName);
//获取到set方法
Method objectFieldSet = tableClass.getMethod(setMethodName,typeClass);
//获取到字段对应的值
Class<? extends ResultSet> resultSetClass = resultSet.getClass();
//组装resultSet的get函数名称
String getMethodName = "get" + METHOD_MAP.get(typeName);
//获取到对应解析函数字节码
Method resultSetGet = resultSetClass.getMethod(getMethodName, String.class);
//创建获取字段注入器
TableColumnGetter tableColumnGetter = new TableColumnGetter(objectFieldSet, resultSetGet, columnLabel);
//整合字段注入器列表
tableColumnGetterList.add(tableColumnGetter);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
//创建表处理器
TableHandler tableHandler = new TableHandler(tableClass,tableColumnGetterList);
//获取表java实例列表
List objectList = tableHandler.getObjectList(resultSet);
return objectList;
}
}
- 首先,从
tableClassMap
的映射中获取T
类对应的表类(tableClass
)。- 然后,获取
tableClass
的所有字段,并对每个字段进行检查。如果字段上有TableColumn
注解,那么就创建一个TableColumnGetter
对象,这个对象包含了字段的set方法、对应的ResultSet
的get方法以及字段名。- 创建
TableColumnGetter
对象的过程中,会根据字段的类型从TYPE_MAP
和METHOD_MAP
两个映射中获取相应的类型类和方法名。- 最后,使用
tableClass
和tableColumnGetterList
创建一个TableHandler
对象,并调用其getObjectList
方法来获取对象列表。
package orm.handler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
public class TableColumnGetter {
//持久对象属性set方法字节码
private Method objectFieldSet;
//resultSet对象get方法字节码
private Method resultSetGet;
//数据库字段名
private String columnLabel;
public TableColumnGetter(Method objectFieldSet, Method resultSetGet,String columnLabel) {
this.objectFieldSet = objectFieldSet;
this.resultSetGet = resultSetGet;
this.columnLabel = columnLabel;
}
//为持久对象对应属性注入值
public <T> void inject(ResultSet resultSet, T object) {
try {
Object result = resultSetGet.invoke(resultSet, columnLabel);
objectFieldSet.invoke(object, result);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
TableColumnGetter
类是一个字段注入器,它包含一个Java对象的set方法、一个ResultSet
的get方法和一个数据库字段名。它的inject
方法用于将ResultSet
中的值注入到Java对象的属性中。
package orm.handler;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class TableHandler<T> {
//持久化对象列表
private List<T> objectList;
//持久化对象字节码
private Class tableClass;
//表列值获取器列表
private List<TableColumnGetter> tableColumnGetterList;
public TableHandler(Class tableClass, List<TableColumnGetter> tableColumnGetterList){
this.tableClass = tableClass;
this.tableColumnGetterList = tableColumnGetterList;
}
//获取持久对象列表
public List<T> getObjectList(ResultSet resultSet) {
if (objectList == null){
objectList = new ArrayList<>();
}
while (true){
try {
if (!resultSet.next()) break;
T object = (T)tableClass.newInstance();
for (TableColumnGetter tableColumnGetter : tableColumnGetterList) {
tableColumnGetter.inject(resultSet,object);
}
objectList.add(object);
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
return objectList;
}
}
TableHandler
类是一个表处理器,它包含一个Java对象列表、一个Java对象的类和一个字段注入器列表。它的getObjectList
方法用于从ResultSet
中获取Java对象列表。这个方法首先创建一个新的Java对象,然后使用字段注入器列表中的每一个注入器将ResultSet
中的值注入到Java对象的属性中,最后将Java对象添加到列表中。
package orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableColumn {
String value();
}
测试
package com;
import orm.annotation.TableColumn;
import java.util.Date;
public class TravelWay {
@TableColumn("wid")
private Integer wid;
@TableColumn("way_name")
private String wayName;
@TableColumn("info")
private String info1;
@TableColumn("sign_begin")
private Date sb;
public Integer getWid() {
return wid;
}
public void setWid(Integer wid) {
this.wid = wid;
}
public String getWayName() {
return wayName;
}
public void setWayName(String wayName) {
this.wayName = wayName;
}
public String getInfo1() {
return info1;
}
public void setInfo1(String info1) {
this.info1 = info1;
}
public Date getSb() {
return sb;
}
public void setSb(Date sb) {
this.sb = sb;
}
@Override
public String toString() {
return "TravelWay{" +
"wid=" + wid +
", wayName='" + wayName + '\'' +
", info1='" + info1 + '\'' +
", sb=" + sb +
'}';
}
}
package com;
import orm.utils.ORMUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
public class Test {
public static void main(String[] args) {
try {
Connection connection = JdbcUtils.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from tb_travel_way");
List<TravelWay> travelWays = ORMUtils.toObjectList(resultSet, TravelWay.class);
for (TravelWay travelWay : travelWays) {
System.out.println(travelWay);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
集成INSERT,UPDATE自动组装
package orm.utils;
import orm.annotation.Key;
import orm.annotation.Table;
import orm.annotation.TableColumn;
import orm.handler.TableColumnGetter;
import orm.handler.TableHandler;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.*;
public class ORMUtils {
private static final String STRING = "java.lang.String";
private static final String INTEGER = "java.lang.Integer";
private static final String DOUBLE = "java.lang.Double";
private static final String CHARACTER = "java.lang.Character";
private static final String BOOLEAN = "java.lang.Boolean";
private static final String SHORT = "java.lang.Short";
private static final String BYTE = "java.lang.Byte";
private static final String LONG = "java.lang.Long";
private static final String FLOAT = "java.lang.Float";
private static final String DATE = "java.util.Date";
private static final Map<String,Class> TYPE_MAP = new HashMap<>();
private static final Map<String,String> METHOD_MAP = new HashMap<>();
static {
TYPE_MAP.put(STRING,String.class);
TYPE_MAP.put(INTEGER,Integer.class);
TYPE_MAP.put(DOUBLE,Double.class);
TYPE_MAP.put(BOOLEAN,Boolean.class);
TYPE_MAP.put(SHORT,Short.class);
TYPE_MAP.put(BYTE,Byte.class);
TYPE_MAP.put(LONG,Long.class);
TYPE_MAP.put(FLOAT,Float.class);
TYPE_MAP.put(DATE, Date.class);
METHOD_MAP.put(STRING,"String");
METHOD_MAP.put(INTEGER,"Int");
METHOD_MAP.put(DOUBLE,"Double");
METHOD_MAP.put(BOOLEAN,"Boolean");
METHOD_MAP.put(SHORT,"Short");
METHOD_MAP.put(BYTE,"Byte");
METHOD_MAP.put(LONG,"Long");
METHOD_MAP.put(FLOAT,"Float");
METHOD_MAP.put(DATE,"Date");
}
private static final String EMPTY = "";
private static final String SPACE = " ";
private static final String BASE_UPDATE = "UPDATE ";
private static final String BASE_SET = " SET ";
private static final String BASE_WHERE = " WHERE 1 = 1 ";
private static final String AND = " AND ";
private static final String BASE_INSERT = "INSERT INTO ";
private static final String START = "(";
private static final String END = ")";
private static final String BASE_VALUES = "VALUES";
private static final String COLUMN_FLAG = "`";
private static final String STRING_FLAG = "'";
private static final String SPLIT = ",";
private static final String EQUAL = " = ";
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public static <T>boolean update(T t,Connection connection){
return update(EMPTY,t,connection);
}
/**
*
* @param sqlAppend 拼接到 WHERE 之后的语句
* @param t 更新对象
* @param connection 连接对象
* @param <T>
* @return
*/
public static <T>boolean update(String sqlAppend,T t, Connection connection){
Class tableClass = t.getClass();
if (tableClass == null){
return false;
}
Table table = (Table)tableClass.getAnnotation(Table.class);
if (table == null){
return false;
}
String sql = BASE_UPDATE + table.value() + BASE_SET;
String where = BASE_WHERE;
//获取属性标注的字段值,自动解析字段
Field[] fields = tableClass.getDeclaredFields();
StringBuilder sqlSB = new StringBuilder();
StringBuilder keySB = new StringBuilder();
sqlSB.append(sql);
keySB.append(where);
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null){
//获取属性名
String propertyName = field.getName();
//get函数名
String getMethodName = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
//字段名
String columnLabel = tableColumn.value();
//获取属性类型
String typeName = field.getGenericType().getTypeName();
try {
//获取到类型字节码
Class typeClass = TYPE_MAP.get(typeName);
//获取到set方法
Method objectFieldGet = tableClass.getMethod(getMethodName);
Object value = objectFieldGet.invoke(t);
if (value != null){
Key key = field.getAnnotation(Key.class);
boolean isKey = false;
StringBuilder sb;
if (key != null){
keySB.append(AND);
isKey = true;
sb = keySB;
}else {
sb = sqlSB;
}
//拼接表字段名
sb.append(COLUMN_FLAG);
sb.append(columnLabel);
sb.append(COLUMN_FLAG);
sb.append(EQUAL);
//拼接值
if (typeClass.getTypeName().equals(STRING)){
sb.append(STRING_FLAG);
sb.append(value);
sb.append(STRING_FLAG);
}else if (typeClass.getTypeName().equals(DATE)){
sb.append(STRING_FLAG);
sb.append(SIMPLE_DATE_FORMAT.format(value));
sb.append(STRING_FLAG);
}else {
sb.append(value);
}
if (!isKey){
sb.append(SPLIT);
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
sql = sqlSB.toString();
where = keySB.toString();
//整理
if (sql.endsWith(SPLIT)){
sql = sql.substring(0,sql.length()-1);
}
//更新语句整合
String updateSql = sql + SPACE + where;
if (sqlAppend != EMPTY){
updateSql += AND + sqlAppend;
}
//执行
boolean execute = false;
try {
Statement statement = connection.createStatement();
execute = statement.execute(updateSql);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return execute;
}
/**
*
* @param t
* @param connection
* @param <T>
* @return
*/
public static <T>boolean insert(T t, Connection connection){
Class tableClass = t.getClass();
if (tableClass == null){
return false;
}
Table table = (Table)tableClass.getAnnotation(Table.class);
if (table == null){
return false;
}
String sql = BASE_INSERT + table.value() + START;
String values = BASE_VALUES + START;
//获取属性标注的字段值,自动解析字段
Field[] fields = tableClass.getDeclaredFields();
StringBuilder sqlSB = new StringBuilder();
sqlSB.append(sql);
StringBuilder valueSB = new StringBuilder();
valueSB.append(values);
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null){
//获取属性名
String propertyName = field.getName();
//get函数名
String getMethodName = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
//字段名
String columnLabel = tableColumn.value();
//获取属性类型
String typeName = field.getGenericType().getTypeName();
try {
//获取到类型字节码
Class typeClass = TYPE_MAP.get(typeName);
//获取到set方法
Method objectFieldGet = tableClass.getMethod(getMethodName);
Object value = objectFieldGet.invoke(t);
if (value != null){
//拼接表字段名
sqlSB.append(COLUMN_FLAG);
sqlSB.append(columnLabel);
sqlSB.append(COLUMN_FLAG);
sqlSB.append(SPLIT);
//拼接值
if (typeClass.getTypeName().equals(STRING)){
valueSB.append(STRING_FLAG);
valueSB.append(value);
valueSB.append(STRING_FLAG);
}else if (typeClass.getTypeName().equals(DATE)){
valueSB.append(STRING_FLAG);
valueSB.append(SIMPLE_DATE_FORMAT.format(value));
valueSB.append(STRING_FLAG);
}else {
valueSB.append(value);
}
valueSB.append(SPLIT);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
sql = sqlSB.toString();
values = valueSB.toString();
//整理
if (sql.endsWith(SPLIT)){
sql = sql.substring(0,sql.length()-1) + END;
}
//整理
if (values.endsWith(SPLIT)){
values = values.substring(0,values.length()-1) + END;
}
//插入语句整合
String insertSql = sql + values;
System.out.println(insertSql);
//执行
boolean execute = false;
try {
Statement statement = connection.createStatement();
execute = statement.execute(insertSql);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return execute;
}
/**
* 自动解析result为对应持久对象数组
* @param resultSet 结果集
* @param tClass 持久对象字节码
* @param <T> 持久对象泛型
* @return
*/
public static <T>List<T> toObjectList(ResultSet resultSet, Class<T> tClass){
List<TableColumnGetter> tableColumnGetterList = new ArrayList<>();
Class tableClass = tClass;
if (tableClass == null){
return new ArrayList<>();
}
//获取属性标注的字段值,自动解析字段
Field[] fields = tableClass.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null){
//获取属性名
String propertyName = field.getName();
//set函数名
String setMethodName = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
//字段名
String columnLabel = tableColumn.value();
//获取属性类型
String typeName = field.getGenericType().getTypeName();
try {
//获取到类型字节码
Class typeClass = TYPE_MAP.get(typeName);
//获取到set方法
Method objectFieldSet = tableClass.getMethod(setMethodName,typeClass);
//获取到字段对应的值
Class<? extends ResultSet> resultSetClass = resultSet.getClass();
//组装resultSet的get函数名称
String getMethodName = "get" + METHOD_MAP.get(typeName);
//获取到对应解析函数字节码
Method resultSetGet = resultSetClass.getMethod(getMethodName, String.class);
//创建获取字段注入器
TableColumnGetter tableColumnGetter = new TableColumnGetter(objectFieldSet, resultSetGet, columnLabel);
//整合字段注入器列表
tableColumnGetterList.add(tableColumnGetter);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
//创建表处理器
TableHandler tableHandler = new TableHandler(tableClass,tableColumnGetterList);
//获取表java实例列表
List objectList = tableHandler.getObjectList(resultSet);
return objectList;
}
}
package orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Key {
}
package orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com