SORM框架实现
作者:互联网
项目地址:https://github.com/CoderJNYao/SORM
主要实现了对数据库的CRUD,po类源码的自动生成,po类与数据库表的映射,类字段信息与数据库字段信息间的映射,暂不支持联合主键。
源码:
bean包下
/**
* 封装表中一个字段的信息
* @author JustinNeil
*
*/
public class ColumnInfo {
/**
* 字段名称
*/
private String name;
/**
* 字段类型
*/
private String dataType;
/**
* 字段的键类型(0:普通键,1:主键,2:外键)
*/
private int keyType;
public ColumnInfo() {
super();
}
public ColumnInfo(String name, String dataType, int keyType) {
super();
this.name = name;
this.dataType = dataType;
this.keyType = keyType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
}
/**
* 封装配置文件信息
* @author JustinNeil
*
*/
public class Configuration {
/**
* 驱动类
*/
private String driver;
/**
* jdbc的URL
*/
private String URL;
/**
* 用户名
*/
private String User;
/**
* 密码
*/
private String Password;
/**
* 正在使用的数据库
*/
private String usingDB;
/**
* 项目的源码路径
*/
private String srcPath;
/**
* 扫描声称java类的包
*/
private String poPackage;
/**
* 当前使用的查询类
*/
private String queryClass;
public Configuration() {
super();
}
public Configuration(String driver, String mysqlURL, String mysqlUser, String mysqlPassword, String usingDB,
String srcPath, String poPackage,String queryClass) {
super();
this.driver = driver;
this.URL = mysqlURL;
this.User = mysqlUser;
this.Password = mysqlPassword;
this.usingDB = usingDB;
this.srcPath = srcPath;
this.poPackage = poPackage;
this.queryClass = queryClass;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getURL() {
return URL;
}
public void setURL(String mysqlURL) {
this.URL = mysqlURL;
}
public String getUser() {
return User;
}
public void setUser(String mysqlUser) {
this.User = mysqlUser;
}
public String getPassword() {
return Password;
}
public void setPassword(String mysqlPassword) {
this.Password = mysqlPassword;
}
public String getUsingDB() {
return usingDB;
}
public void setUsingDB(String usingDB) {
this.usingDB = usingDB;
}
public String getSrcPath() {
return srcPath;
}
public void setSrcPath(String srcPath) {
this.srcPath = srcPath;
}
public String getPoPackage() {
return poPackage;
}
public void setPoPackage(String poPackage) {
this.poPackage = poPackage;
}
public String getQueryClass() {
return queryClass;
}
public void setQueryClass(String queryClass) {
this.queryClass = queryClass;
}
}
/**
* 封装了java类的属性和get,set方法
* @author JustinNeil
*
*/
public class JavaFieldGetSet {
/**
* 属性的源码信息
*/
private String fieldInfo;
/**
* get方法的源码信息
*/
private String getInfo;
/**
* set方法的源码信息
*/
private String setInfo;
public JavaFieldGetSet() {
super();
}
public JavaFieldGetSet(String fieldInfo, String getInfo, String setInfo) {
super();
this.fieldInfo = fieldInfo;
this.getInfo = getInfo;
this.setInfo = setInfo;
}
public String getFieldInfo() {
return fieldInfo;
}
public void setFieldInfo(String fieldInfo) {
this.fieldInfo = fieldInfo;
}
public String getGetInfo() {
return getInfo;
}
public void setGetInfo(String getInfo) {
this.getInfo = getInfo;
}
public String getSetInfo() {
return setInfo;
}
public void setSetInfo(String setInfo) {
this.setInfo = setInfo;
}
@Override
public String toString() {
return getFieldInfo()+"\n"+getSetInfo()+"\n"+getGetInfo()+"";
}
}
/**
* 封装表结构的信息
* @author JustinNeil
*
*/
public class TableInfo {
/**
* 表名
*/
private String tname;
/**
* 所有字段信息
*/
private Map<String,ColumnInfo> columns;
/**
* 如果有联合主键,在这里存储
*/
private List<ColumnInfo> priKeys;
public TableInfo() {
super();
}
public TableInfo(String tname, Map<String, ColumnInfo> columns, List<ColumnInfo> priKeys) {
super();
this.tname = tname;
this.columns = columns;
this.priKeys = priKeys;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public Map<String, ColumnInfo> getColnums() {
return columns;
}
public void setColnums(Map<String, ColumnInfo> columns) {
this.columns = columns;
}
public List<ColumnInfo> getPriKeys() {
return priKeys;
}
public void setPriKeys(List<ColumnInfo> priKeys) {
this.priKeys = priKeys;
}
}
core包
public interface CallBack {
public Object doExecute(Connection con,PreparedStatement ps,ResultSet rs);
}
/**
* 根据配置信息,维持连接对象的管理
* @author JustinNeil
*
*/
public class DBManager {
private static Configuration conf;
private static DruidDataSource dds = new DruidDataSource();
static {
Properties properties = new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
conf = new Configuration();
conf.setUsingDB(properties.getProperty("usingDB"));
if(conf.getUsingDB().equals("mysql")){
conf.setDriver(properties.getProperty("mysqlDriver"));
conf.setURL(properties.getProperty("mysqlURL"));
conf.setUser(properties.getProperty("mysqlUser"));
conf.setPassword(properties.getProperty("mysqlPassword"));
}else if(conf.getUsingDB().equals("oracle")){
conf.setDriver(properties.getProperty("oracleDriver"));
conf.setURL(properties.getProperty("oracleURL"));
conf.setUser(properties.getProperty("oracleUser"));
conf.setPassword(properties.getProperty("oraclePassword"));
}
conf.setSrcPath(properties.getProperty("srcPath"));
conf.setPoPackage(properties.getProperty("poPackage"));
conf.setQueryClass((properties.getProperty("queryClass")));
dds.setDriverClassName(conf.getDriver());
dds.setUrl(conf.getURL());
dds.setUsername(conf.getUser());
dds.setPassword(conf.getPassword());
dds.setInitialSize(5);
dds.setMaxActive(20);
}
public static Connection getConnection(){
try {
return dds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static void closeSourse(ResultSet rs,PreparedStatement ps,Connection con){
try {
if(rs != null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(ps != null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public static void closeSourse(PreparedStatement ps,Connection con){
try {
if(ps != null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static Configuration getConfiguration(){
return conf;
}
}
/**
* 负责查询(对外提供服务的核心类)
* @author JustinNeil
*
*/
@SuppressWarnings("all")
public abstract class Query implements Cloneable{
public Object executeDMLTemplement(String sql, Object[] params,Class clazz,CallBack callBack){
Connection con = DBManager.getConnection();
PreparedStatement ps;
TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
try {
ps = con.prepareStatement(sql);
JDBCUtils.handleParams(ps, params);
ResultSet rs = ps.executeQuery();
return callBack.doExecute(con, ps, rs);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 执行一条DML语句
* @param sql
* @param params
* @return 返回DML语句更新的数据条数
*/
public int executeDML(String sql, Object[] params) {
Connection con = DBManager.getConnection();
PreparedStatement ps = null;
try {
ps = con.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i+1, params[i]);
}
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBManager.closeSourse(ps, con);
}
return 0;
}
/**
* 讲一个对象存储到数据库中
* @param bean 要存储的实体类对象
*/
public void insert(Object obj) {
Class<?> c = obj.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(c);
String tableName = tableInfo.getTname();
StringBuilder sql = new StringBuilder();
List<Object> values = new ArrayList<Object>();
int valueCount = 0;
sql.append("INSERT INTO "+tableName+" (");
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
Object fieldValue = ReflectUtils.invokeGet(fieldName, obj);
if(fieldValue != null){
sql.append(fieldName+",");
values.add(fieldValue);
valueCount++;
}
}
sql.setCharAt(sql.length()-1, ')');
sql.append(" VALUES(");
for(int i=0;i<valueCount;i++){
sql.append("?,");
}
sql.setCharAt(sql.length()-1, ')');
executeDML(sql.toString(), values.toArray());
}
/**
* 删除指定类对应表中指定id的记录
* @param clazz 跟表对应的Class类对象
* @param id 主键id
*/
public void delete(Class clazz, Object id) {
TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
String tableName = tableInfo.getTname();
String priKeyName = tableInfo.getPriKeys().get(0).getName();
String sql = "DELETE FROM "+tableName+" WHERE "+priKeyName+"=?";
executeDML(sql, new Object[]{id});
}
/**
* 根据对象删除数据库中的对应记录(根据对象的类获取对应表,根据对象的主键id获取对应记录)
* @param o 需要删除记录的对应对象
*/
public void delete(Object o) {
Class<?> c = o.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(c);
String priKeyName = tableInfo.getPriKeys().get(0).getName();
Object priKey = ReflectUtils.invokeGet(priKeyName, o);
delete(c, priKey);
}
/**
* 更新对象对应表中数据的值,并且只更新指定字段的值
* @param o 需要更新的对象
* @param fieldNames 更新的属性列表
* @return 影响的数据行数
*/
public int update(Object o, String[] fieldNames) {
Class<?> c = o.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(c);
String tableName = tableInfo.getTname();
List<Object> values = new ArrayList<Object>();
ColumnInfo columnInfo = tableInfo.getPriKeys().get(0);
StringBuilder sql = new StringBuilder();
sql.append("UPDATE "+tableName+" SET ");
for (String fieldName : fieldNames) {
sql.append(fieldName+"=?,");
values.add(ReflectUtils.invokeGet(fieldName, o));
}
sql.setCharAt(sql.length()-1, ' ');
sql.append("WHERE ");
sql.append(columnInfo.getName()+"=?");
values.add(ReflectUtils.invokeGet(columnInfo.getName(), o));
executeDML(sql.toString(), values.toArray());
return 0;
}
/**
* 查询多行记录,并将每行记录封装到Clazz指定的类的对象中
* @param sql 查询语句
* @param clazz 封装数据的Javabean类的Class对象
* @param params sql的参数
* @return 查询到的结果
*/
public List queryRows(final String sql,final Class clazz,final Object[] params) {
List<Object> list = new ArrayList<Object>();
executeDMLTemplement(sql, params, clazz, new CallBack() {
@Override
public Object doExecute(Connection con, PreparedStatement ps, ResultSet rs) {
ResultSetMetaData metaData;
try {
metaData = rs.getMetaData();
while(rs.next()){
Object obj = clazz.newInstance();
for(int i=0;i<metaData.getColumnCount();i++){
String fieldName = metaData.getColumnLabel(i+1);
Object value = rs.getObject(i+1);
ReflectUtils.invokeSet(fieldName, obj, value);
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
});
return list;
}
/**
* 查询一行记录,并封装到Clazz指定的类的对象中
* @param sql 查询语句
* @param clazz 封装数据的Javabean类的Class对象
* @param params sql的参数
* @return 查询到的结果
*/
public Object queryUniqueRow(String sql, Class clazz, Object[] params) {
List list = queryRows(sql, clazz, params);
return list==null?null:list.size()==0?null:list.get(1);
}
/**
* 查询一个值(数据库的一行一列),并返回该值
* @param sql 查询语句
* @param params sql的参数
* @return 查询到的值
*/
public Object queryValue(String sql, Object[] params) {
Object object = null;
object = executeDMLTemplement(sql, params, null, new CallBack() {
@Override
public Object doExecute(Connection con, PreparedStatement ps, ResultSet rs) {
try {
if(rs.next()){
return rs.getObject(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
});
return object;
}
/**
* 查询一个数字,并返回该数字
* @param sql 查询语句
* @param params sql的参数
* @return 查询到的值
*/
public Number queryNumber(String sql, Object[] params) {
return (Number)queryValue(sql, params);
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class MySQLQuery extends Query{
}
/**
* MySQL数据库类型与java类型的转化器
* @author JustinNeil
*
*/
public class MySQLTypeConvertor implements TypeConvertor{
@Override
public String databaseTypeToJavaType(String columnType) {
if("varchar".equalsIgnoreCase(columnType)||"char".equalsIgnoreCase(columnType)){
return "String";
}else if("int".equalsIgnoreCase(columnType)
||"tinyint".equalsIgnoreCase(columnType)
||"smallint".equalsIgnoreCase(columnType)
||"integer".equalsIgnoreCase(columnType)){
return "Integer";
}else if ("bigint".equalsIgnoreCase(columnType)) {
return "Long";
}else if("double".equalsIgnoreCase(columnType)||"float".equalsIgnoreCase(columnType)){
return "Double";
}else if("clob".equalsIgnoreCase(columnType)){
return "java.sql.Clob";
}else if("date".equalsIgnoreCase(columnType)){
return "java.sql.Date";
}else if("time".equalsIgnoreCase(columnType)){
return "java.sql.Time";
}else if("timestamp".equalsIgnoreCase(columnType)){
return "java.sql.Timestamp";
}
return null;
}
@Override
public String javaTypeToDatabaseType(String javaDataType) {
// TODO Auto-generated method stub
return null;
}
}
public class QueryFactory {
private static Class c;
private static Query query;
static {
try {
c = Class.forName(DBManager.getConfiguration().getQueryClass());
query = (Query) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Query createQuery(){
try {
return (Query) query.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
/**
* 负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构
* @author JustinNeil
*
*/
public class TableContext {
/**
* 表名为key,表信息对象为value;
*/
public static Map<String, TableInfo> tables = new HashMap<String,TableInfo>();
/**
* 将po的Class对象与表信息对象关联,便于重用
*/
public static Map<Class<?>, TableInfo> poClassTableMap = new HashMap<Class<?>,TableInfo>();
static{
try {
Connection con = DBManager.getConnection();
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getTables(null, "%", "%", new String[]{"TABLE"});
while (rs.next()) {
String tableName = (String)rs.getObject("TABLE_NAME");
TableInfo ti = new TableInfo(tableName, new HashMap<String,ColumnInfo>(), new ArrayList<ColumnInfo>());
tables.put(tableName, ti);
ResultSet set = dbmd.getColumns(null, "%", tableName,"%");
while(set.next()){
ColumnInfo ci = new ColumnInfo(set.getString("COLUMN_NAME"),set.getString("TYPE_NAME") , 0);
ti.getColnums().put(set.getString("COLUMN_NAME"), ci);
}
ResultSet keySet = dbmd.getPrimaryKeys(null, "%", tableName);
while (keySet.next()) {
ColumnInfo keyCI = (ColumnInfo)ti.getColnums().get(keySet.getString("COLUMN_NAME"));
keyCI.setKeyType(1);
ti.getPriKeys().add(keyCI);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
updateJavaVoFile();
loadVoTable();
}
/**
* 根据表结构,更新po包中的java类
*/
public static void updateJavaVoFile(){
Map<String,TableInfo> tableMap = TableContext.tables;
for (String string : tableMap.keySet()) {
TableInfo tableInfo = tableMap.get(string);
JavaFileUtils.createJavaVoFile(tableInfo, new MySQLTypeConvertor());
}
}
/**
* 加载po包下的类,与表一一对应
*/
public static void loadVoTable(){
for(TableInfo tableInfo:tables.values()){
Class<?> c;
try {
c = Class.forName(DBManager.getConfiguration().getPoPackage()+"."+
StringUtils.firstCharToUpper(tableInfo.getTname()));
poClassTableMap.put(c, tableInfo);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
/**
* 负责java数据类型和数据库数据类型的互相转换
* @author JustinNeil
*/
public interface TypeConvertor {
/**
* 将数据库类型转换成java类型
* @param columnType 数据库字段的数据类型
* @return java的数据类型
*/
public String databaseTypeToJavaType(String columnType);
/**
* 将java类型转换成数据库类型
* @param javaDataType java类型
* @return 数据库字段的数据类型
*/
public String javaTypeToDatabaseType(String javaDataType);
}
工具类
/**
* 封装了生成Java源码的操作
* @author JustinNeil
*
*/
public class JavaFileUtils {
/**
* 根据字段信息生成Java源码
* @param columnInfo 字段信息
* @param typeConvertor 类型转换器
* @return Java属性和get,set方法源码
*/
public static JavaFieldGetSet createFieldGetSetSRC(ColumnInfo columnInfo,TypeConvertor typeConvertor){
JavaFieldGetSet jfgs = new JavaFieldGetSet();
String javaFieldType = typeConvertor.databaseTypeToJavaType(columnInfo.getDataType());
jfgs.setFieldInfo("\tprivate "+javaFieldType+" "+columnInfo.getName()+";\n");
StringBuilder getSrc = new StringBuilder();
getSrc.append("\tpublic "+javaFieldType+" get"+StringUtils.firstCharToUpper(columnInfo.getName())+"(){\n"+
"\t\treturn "+ columnInfo.getName()+
";\n\t}\n");
jfgs.setGetInfo(getSrc.toString());
StringBuilder setSrc = new StringBuilder();
setSrc.append("\tpublic set"+StringUtils.firstCharToUpper(columnInfo.getName())+"("+javaFieldType+" "+columnInfo.getName()+"){\n"+
"\t\tthis."+columnInfo.getName()+"="+columnInfo.getName()+
";\n\t}\n");
jfgs.setSetInfo(setSrc.toString());
return jfgs;
}
public static String createJavaSrc(TableInfo tableInfo,TypeConvertor typeConvertor){
StringBuilder sb = new StringBuilder();
String tableName = tableInfo.getTname();
List<ColumnInfo> colList = new ArrayList<ColumnInfo>();
Map<String,ColumnInfo> colMap = tableInfo.getColnums();
Set<String> kSet = colMap.keySet();
for (String string : kSet) {
colList.add(colMap.get(string));
}
//包名
sb.append("package "+DBManager.getConfiguration().getPoPackage()+";\n\n");
//import语句
sb.append("import java.sql.*;\n");
sb.append("import java.util.*;\n\n");
//类定义
sb.append("public class "+StringUtils.firstCharToUpper(tableName)+"{\n\n");
//字段定义
for (ColumnInfo c : colList) {
sb.append("\tprivate "+typeConvertor.databaseTypeToJavaType(c.getDataType())+" "+c.getName()+";\n");
}
sb.append("\n");
//get,set方法定义
for (ColumnInfo c : colList) {
sb.append("\tpublic "+typeConvertor.databaseTypeToJavaType(c.getDataType())+" get"+StringUtils.firstCharToUpper(c.getName())+
"(){\n"+"\t\treturn "+ c.getName()+";\n\t}\n");
sb.append("\tpublic void set"+StringUtils.firstCharToUpper(c.getName())+"("+typeConvertor.databaseTypeToJavaType(c.getDataType())+
" "+c.getName()+"){\n"+"\t\tthis."+c.getName()+"="+c.getName()+";\n\t}\n");
}
//类体结束
sb.append("}\n");
return sb.toString();
}
public static void createJavaVoFile(TableInfo tableInfo,TypeConvertor typeConvertor){
String src = createJavaSrc(tableInfo, typeConvertor);
BufferedWriter bw = null;
String srcPath = DBManager.getConfiguration().getSrcPath()+"\\"+DBManager.getConfiguration().getPoPackage().replaceAll("\\.", "\\\\");
File file = new File(srcPath+"\\"+StringUtils.firstCharToUpper(tableInfo.getTname())+".java");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
bw = new BufferedWriter(new FileWriter(file));
bw.write(src);
System.out.println("建立表"+tableInfo.getTname()+"对应的Java类:"+file.getName());
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 封装常用JDBC操作
* @author JustinNeil
*
*/
public class JDBCUtils {
/**
* SQL语句参数补全
* @param ps 存放SQL语句的PreparedStatement对象
* @param objects 参数数组
*/
public static void handleParams(PreparedStatement ps,Object[] objects){
for(int i=0;i<objects.length;i++){
try {
ps.setObject(i+1, objects[i]);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 封装常用反射操作
* @author JustinNeil
*
*/
public class ReflectUtils {
/**
* 封装调用get方法
* @param fieldName 字段名
* @param obj 调用方法的对象
* @return 字段值
*/
public static Object invokeGet(String fieldName,Object obj){
Class<?> c = obj.getClass();
try {
Method m = c.getDeclaredMethod("get"+StringUtils.firstCharToUpper(fieldName));
return m.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 封装调用set方法
* @param fieldName 字段名
* @param obj 调用方法的对象
* @param value 字段值
*/
public static void invokeSet(String fieldName,Object obj,Object value){
Class<?> c = obj.getClass();
try {
Method m = c.getDeclaredMethod("set"+StringUtils.firstCharToUpper(fieldName),value.getClass());
m.invoke(obj,value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 封装常用字符串操作
* @author JustinNeil
*
*/
public class StringUtils {
/**
* 将目标字符串的首字母转为大写
* @param str 原字符串
* @return 首字母大写的字符串
*/
public static String firstCharToUpper(String str){
return str.substring(0, 1).toUpperCase()+str.substring(1);
}
/**
* 将目标字符串的转为小写
* @param str 原字符串
* @return 小写的字符串
*/
public static String toLower(String str){
return str.toLowerCase();
}
}
标签:return,String,框架,实现,void,new,sql,SORM,public 来源: https://blog.csdn.net/yjn1995/article/details/90672983