关于注解
某个类与其对应数据库表的映射关系用注解来表示
表注解
应用于类,在使用该注解时其属性 name 必须赋值
package com.mec.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 name();
}
关键字注解
作用于类的成员,来表明该成员是否对应表中的关键字
如果该成员含有这个注解,则表明该成员所对应的字段为该表的关键字
package com.mec.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 {
}
字段注解
字段名默认为空串,如果类的成员名与字段名相同则不需要重新给column属性赋值
package com.mec.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 Column {
String column() default "";
}
关于数据库工具
PropertyColumn 类
该类主要处理字段与其对应类的成员的关系
package com.mec.orm.core;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PropertyColumn {
private String column;
private Field field;
public PropertyColumn() {
}
public void setProperty(ResultSet resultSet,Object obj) {
try {
Object value = resultSet.getObject(column);
field.setAccessible(true);
field.set(obj, value);
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
@Override
public String toString() {
return column + "< - >" + field;
}
}
ClassTable类
该类主要处理某个类与其对应表的关系
package com.mec.orm.core;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ClassTable {
private Class<?> klass;
private String table;
private List<PropertyColumn> fieldList;
private PropertyColumn id;
ClassTable() {
fieldList = new ArrayList<>();
}
void setFieldFromResultSet(ResultSet resultset,Object obj) {
for(PropertyColumn field : fieldList) {
field.setProperty(resultset, obj);
}
}
void addProperty(PropertyColumn property) {
fieldList.add(property);
}
Class<?> getKlass() {
return klass;
}
void setKlass(Class<?> klass) {
this.klass = klass;
}
String getTable() {
return table;
}
void setTable(String table) {
this.table = table;
}
List<PropertyColumn> getFieldList() {
return fieldList;
}
void setFieldList(List<PropertyColumn> fieldList) {
this.fieldList = fieldList;
}
PropertyColumn getId() {
return id;
}
void setId(PropertyColumn id) {
this.id = id;
}
String getIdString() {
return table + "." + id.getColumn();
}
String getColumnString() {
StringBuffer res = new StringBuffer();
boolean first = true;
for(PropertyColumn field : fieldList) {
res.append(first ? "" : ", ")
.append(table).append(".")
.append(field.getColumn());
first = false;
}
return res.toString();
}
int getfieldCount() {
return fieldList.size();
}
@Override
// 便于测试
public String toString() {
StringBuffer res = new StringBuffer("类");
res.append(klass.getName()).append('\n')
.append("表:").append(table).append('\n');
for(PropertyColumn pc : fieldList) {
res.append('\t').append(pc.getField().getName())
.append("< - > ")
.append(pc.getColumn())
.append('\n');
}
res.append(id).append('\n');
return res.toString();
}
}
ClassTableFactory类
该类主要解析类与表的映射关系(支持xml文件和注解表示)
ClassTableFactory 方法:解析该类的注解得到映射关系
loadMapping方法:利用xml解析工具,解析xml文件得到映射关系
package com.mec.orm.core;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Element;
import com.mec.orm.annotation.Column;
import com.mec.orm.annotation.Key;
import com.mec.orm.annotation.Table;
import com.mec.util.XMLParser;
public class ClassTableFactory {
private static final Map<String,ClassTable> classtableMap;
static {
classtableMap = new HashMap<>();
}
public ClassTableFactory() {
}
public static void classTableParser(Class<?> klass) {
if(!klass.isAnnotationPresent(Table.class)) {
return;
}
Table table = klass.getAnnotation(Table.class);
String tablename = table.name();
ClassTable ct = new ClassTable();
ct.setKlass(klass);
ct.setTable(tablename);
Field[] fields = klass.getDeclaredFields();
boolean hasKey = false;
for(Field field : fields) {
if (!field.isAnnotationPresent(Column.class)) {
continue;
}
String column = field.getName();
Column f = field.getAnnotation(Column.class);
String col = f.column();
if(col.length() > 0) {
column = col;
}
PropertyColumn property = new PropertyColumn();
property.setField(field);
property.setColumn(column);
ct.addProperty(property);
if(!hasKey && field.isAnnotationPresent(Key.class)) {
ct.setId(property);
hasKey = true;
}
}
classtableMap.put(klass.getName(), ct);
}
public static void loadMapping(String path) {
try {
new XMLParser() {
@Override
public void dealElement(Element element, int index) {
String className = element.getAttribute("class");
String tableName = element.getAttribute("table");
ClassTable ct = new ClassTable();
try {
Class<?> klass = Class.forName(className);
ct.setKlass(klass);
ct.setTable(tableName);
new XMLParser() {
@Override
public void dealElement(Element element, int index) {
String id = element.getAttribute("key");
String property = element.getAttribute("property");
String column = element.getAttribute("name");
PropertyColumn pc = new PropertyColumn();
try {
pc.setField(klass.getDeclaredField(property));
pc.setColumn(column);
if(id.length() > 0) {
ct.setId(pc);
}
ct.addProperty(pc);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}.parse(element,"column");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
classtableMap.put(className, ct);
}
}.parse(XMLParser.loadXML(path),"mapping");
} catch (Exception e) {
e.printStackTrace();
};
}
public static ClassTable getClassTable(Class<?> klass) {
return classtableMap.get(klass.getName());
}
public static ClassTable getClassTable(String className) {
return classtableMap.get(className);
}
}
Database 类
结合使用properties解析工具完成数据库的连接,以及记录的插入、修改、删除、查询等操作
package com.mec.orm.core;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.mec.util.PropertiesParser;
public class Database {
private static Connection connection;
public Database() {
}
public static void loadDatabaseConfig(String path) {
PropertiesParser.loadProperties(path);
}
private static Connection getConnection() {
if(connection == null) {
try {
Class.forName(PropertiesParser.value("driver"));
connection = (Connection) DriverManager.getConnection(
PropertiesParser.value("url"),
PropertiesParser.value("user"),
PropertiesParser.value("password")
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return connection;
}
@SuppressWarnings("unchecked")
public <T> List<T> list(Class<?> klass){
ClassTable ct = getClassTable(klass);
if(ct == null) {
return null;
}
String sql = "SELECT " + ct.getColumnString() + " FROM " + ct.getTable();
List<T> result = new ArrayList<>();
try {
PreparedStatement state = getConnection().prepareStatement(sql);
ResultSet rs = state.executeQuery();
while(rs.next()) {
Object obj = klass.newInstance();
ct.setFieldFromResultSet(rs, obj);
result.add((T) obj);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
@SuppressWarnings("unchecked")
public <T> T get(Class<?> klass,Object id) {
ClassTable ct = getClassTable(klass);
if(ct == null) {
return null;
}
String sql = "SELECT " + ct.getColumnString() + " FROM " + ct.getTable()
+ " WHERE " + ct.getIdString() + "=?";
Connection connection = getConnection();
try {
PreparedStatement state = connection.prepareStatement(sql);
state.setObject(1,id);
ResultSet rs = state.executeQuery();
if(rs.next()) {
Object obj = klass.newInstance();
ct.setFieldFromResultSet(rs, obj);
return (T) obj;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public <T> int save(T obj){
Class<?> klass = obj.getClass();
ClassTable ct = getClassTable(klass);
String sql = getSQLInsertInto(ct);
PreparedStatement state = setObject(sql, obj);
try {
state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public <T> int modify(T obj,Object id) {
Class<?> klass = obj.getClass();
ClassTable ct = getClassTable(klass);
String sql = getUpdateSQL(ct);
sql = sql.replaceAll(","," = ?,") + "= ?";
sql = sql + " WHERE "+ ct.getIdString() + "=" + id;
PreparedStatement state = setObject(sql, obj);
try {
state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public <T> int delete(T obj,Object id) {
Class<?> klass = obj.getClass();
ClassTable ct = getClassTable(klass);
StringBuffer sql = new StringBuffer();
sql.append("DELETE FROM ").append(ct.getTable())
.append(" WHERE ").append(ct.getIdString())
.append("=").append(id);
Connection connection = getConnection();
try {
PreparedStatement state = connection.prepareStatement(sql.toString());
state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
private String getUpdateSQL(ClassTable ct) {
StringBuffer sql = new StringBuffer();
sql.append("UPDATE ").append(ct.getTable())
.append(" SET ").append(ct.getColumnString());
return sql.toString();
}
private PreparedStatement setObject(String sql,Object obj) {
Connection connection = getConnection();
PreparedStatement state = null;
try {
state = connection.prepareStatement(sql);
Class<?> klass = obj.getClass();
Field[] fields = klass.getDeclaredFields();
int i = 1;
for(Field field : fields) {
field.setAccessible(true);
Object value;
try {
value = field.get(obj);
} catch (Exception e) {
value = null;
}
state.setObject(i++, value);
}
} catch (SQLException e) {
e.printStackTrace();
}
return state;
}
private String getSQLInsertInto(ClassTable ct) {
StringBuffer sql = new StringBuffer("INSERT INTO ");
sql.append(ct.getTable()).append(" (")
.append(ct.getColumnString()).append(") ")
.append("VALUES(");
int count = ct.getfieldCount();
boolean first = true;
for(int i = 0;i < count;i++) {
sql.append(first ? "?" : ",?");
first = false;
}
sql.append(")");
return sql.toString();
}
private ClassTable getClassTable(Class<?> klass) {
ClassTable ct = ClassTableFactory.getClassTable(klass);
if(ct == null) {
ClassTableFactory.classTableParser(klass);
ct = ClassTableFactory.getClassTable(klass);
}
return ct;
}
public int executeUpdate(String SQLString) {
Connection connection = getConnection();
try {
PreparedStatement state = connection.prepareStatement(SQLString);
return state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
}
public ResultSet executeQuery(String sql) {
ResultSet rs = null;
Connection connection = getConnection();
try {
PreparedStatement state = connection.prepareStatement(sql);
return state.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
}
测试代码
SDMmodel类
package com.mec.orm.model;
import com.mec.orm.annotation.Column;
import com.mec.orm.annotation.Key;
import com.mec.orm.annotation.Table;
@Table(name = "sys_sch_dep_maj_info")
public class SDMmodel {
@Column
@Key
private String id;
@Column
private String name;
@Column
private boolean status;
public SDMmodel() {
}
public SDMmodel(String id, String name, boolean status) {
this.id = id;
this.name = name;
this.status = status;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
@Override
public String toString() {
StringBuffer res = new StringBuffer();
res.append("'" + getId() + "','"
+ getName() + "'," + (isStatus()? "1" : "0"));
return res.toString();
}
}
package com.mec.orm.test;
import com.mec.orm.core.Database;
import com.mec.orm.model.SDMmodel;
public class TestForOrm {
public static void main(String[] args) {
Database.loadDatabaseConfig("/dataBase.properties");
Database database = new Database();
SDMmodel sdm = new SDMmodel("060101","vivi",true);
database.save(sdm);
// SDMmodel sdmNew = new SDMmodel("060101", "sehun", true);
// database.modify(sdmNew,sdmNew.getId());
// database.delete(sdm, sdm.getId());
}
}
运行结果
原始数据库表
执行save()方法之后