网站建设连接数据库,网址转换二维码,可以入侵的网站,新1站网站建设经过几天的业余开发#xff0c;今天终于到ORM对业务api本身的实现了#xff0c;首先实现第一个查询的api
老的C#定义如下
因为Java的泛型不纯#xff0c;所以无法用只带泛型的方式实现api#xff0c;对查询类的api做了调整#xff0c;第一个参数要求传入实体对象
首先…经过几天的业余开发今天终于到ORM对业务api本身的实现了首先实现第一个查询的api
老的C#定义如下
因为Java的泛型不纯所以无法用只带泛型的方式实现api对查询类的api做了调整第一个参数要求传入实体对象
首先补充基础方法
反射工具类用来给实体设置属性值
package LIS.Core.Util;import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLClassLoader;//反射工具类
public class ReflectUtil {//设置对象指定属性名字的值public static void SetObjValue(Object obj,String name,Object val){try {Class c obj.getClass();//得到列信息Field declaredField c.getDeclaredField(name);//布尔的处理if(declaredField.getType()Boolean.class) {if(val.toString()1){valBoolean.TRUE;}else if(val.toString()0){valBoolean.FALSE;}else{valBoolean.TRUE;}}//布尔的处理else if(declaredField.getType()boolean.class) {if(val.toString()1){valtrue;}else if(val.toString()0){valfalse;}else{valtrue;}}//布尔的处理else if(declaredField.getType()int.class) {if(valnull){val0;}}declaredField.set(obj, val);}catch (Exception ex){ex.printStackTrace();}}/// summary/// 用类型全名和程序集全名获得类型/// /summary/// param nametypeName类型全名/param/// param nameassemblyName程序集名/param/// returns/returnspublic static Class GetType(String typeName, String assemblyName){try {//得到根路径Class? clazz ReflectUtil.class;ClassLoader classLoader clazz.getClassLoader();URL resourceURL1 classLoader.getResource();String bashePath resourceURL1.getFile();//组装成jar包路径String jarPathbashePathassemblyName.jar;File file new File(jarPath);if (!file.exists()) {throw new Exception(未能找到jarPath的文件);}//反射得到类型//自己生成jar包路径URL url file.toURI().toURL();URL[] urls new URL[]{url};//加载程序集URLClassLoader loader new URLClassLoader(urls);//加载类Class c loader.loadClass(typeName);if(c!null){return c;}else{throw new Exception(未能构建类型typeName);}}catch (Exception ex){ex.printStackTrace();}return null;}
}
HashTable转参数列表工具类把老的HashTable传参数转换为内部ParaDto
package LIS.Core.Util;
import LIS.Core.Dto.ParamDto;
import java.util.List;
import java.util.HashMap;
import java.util.*;import java.util.Hashtable;public class HashToParam {//哈希表得到参数列表public static ListParamDto GetParam(Hashtable hs){ListParamDto retListnew ArrayListParamDto();Enumeration keys hs.keys();while(keys.hasMoreElements()) {String str (String) keys.nextElement();ParamDto dtonew ParamDto();dto.Keystr;dto.Valuehs.get(str);retList.add(dto);}return retList;}
}
参数实体传sql参数用
package LIS.Core.Dto;
//ORM参数对象
public class ParamDto {/// summary/// 关键字段名称/// /summarypublic Object Key;/// summary/// 关键字段值/// /summarypublic Object Value;///构造函数public ParamDto(){}//构造函数public ParamDto(Object key, Object value){this.Key key;this.Value value;}
}
ORM的FindAll实现
package LIS.DAL.ORM.EntityManager;import LIS.Core.Context.ObjectContainer;import java.lang.reflect.Type;
import java.sql.*;
import java.util.List;
import java.util.*;
import LIS.Core.Dto.*;public class EntityManagerImpl implements LIS.DAL.ORM.EntityManager.IEntityManager {/// summary/// 存会话信息/// /summaryLIS.Model.Bussiness.Sessions Sessionnull;/// summary/// 开启事务该方法初始化一个新的事务/// /summarypublic void BeginTransaction(){}/// summary/// 数据查询/// /summary/// typeparam nameT实体类型/typeparam/// param namemodel传入一个空的或者非空的实体对象/param/// param nameparam参数哈希表数据库列名称和值的键值对/param/// param nameorderField排序字段如RowID ASC,Name DESC/param/// param namepageSize页面大小。为-1无条件查询所有数据/param/// param namepageIndex页码。为-1无条件查询所有数据/param/// returns对象集合/returnspublic T ListT FindAll(T model,Hashtable param, String orderField, int pageSize, int pageIndex){ListT retList new ArrayListT();//建立连接Connection conn null;//commandPreparedStatement stmt null;try {Class c model.getClass();//转换参数ListParamDto paraLIS.Core.Util.HashToParam.GetParam(param);//得到数据库驱动工厂LIS.DAL.ORM.DBUtility.IDbFactory factory LIS.Core.Context.ObjectContainer.GetTypeObject(LisMianDbFactory);//得到表信息LIS.DAL.ORM.Common.TableInfo tableInfo LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);//得到sql语句String sql LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(factory, tableInfo, para, null, null, orderField, false);//连接串最后的是数据库名称String url factory.GetConnectionString();//用户String user factory.GetUserName();//密码String password factory.GetUserPass();//加载驱动factory.LoadDriver();//数据库连接conn DriverManager.getConnection(url,user,password);stmt conn.prepareStatement(sql);//设置数据参数LIS.DAL.ORM.DBUtility.DBParaUtil.SetDBPara(stmt,para);//执行sql得到结果集ResultSet rs stmt.executeQuery();// 处理查询结果while (rs.next()) {//一行数据T oneRow (T) c.newInstance();//循环读取列数据放入实体中for(int j0;jtableInfo.ColList.size();j){String ColNametableInfo.ColList.get(j).Name;Object valrs.getObject(ColName);//设置属性值LIS.Core.Util.ReflectUtil.SetObjValue(oneRow,ColName,val);}retList.add(oneRow);}// 关闭 ResultSet、Statement 和 Connection 对象rs.close();}catch (Exception ex){ex.printStackTrace();}finally {// 关闭资源try {if (stmt ! null){stmt.close();}}catch (Exception se2) {}try {if (conn ! null){conn.close();}}catch (Exception se2) {}}return retList;}/// summary/// 查询测试/// /summarypublic void DBSelectTest(){LIS.DAL.ORM.DBUtility.IDbFactory factory LIS.Core.Context.ObjectContainer.GetTypeObject(LisMianDbFactory);//连接串最后的是数据库名称String url factory.GetConnectionString();//用户String user factory.GetUserName();//密码String password factory.GetUserPass();//建立连接Connection conn null;//commandPreparedStatement stmt null;try {//加载驱动factory.LoadDriver();conn DriverManager.getConnection(url,user,password);//编译和执行SQL语句,传输SQL参数查询1997-2000行String sql SELECT * FROM dbo.SYS_Form where \RowID\? and \RowID\?;;stmt conn.prepareStatement(sql);stmt.setInt(1,1997);stmt.setInt(2,2000);//结果集ResultSet rs stmt.executeQuery();// 处理查询结果while (rs.next()) {//取列数据int RowID rs.getInt(RowID);String CName rs.getString(CName);String Path rs.getString(Path);//输出System.out.println(RowID \t CName \t Path);}// 关闭 ResultSet、Statement 和 Connection 对象rs.close();}catch (Exception ex) {// 处理 JDBC 异常ex.printStackTrace();}finally {// 关闭资源try {if (stmt ! null){stmt.close();}}catch (Exception se2) {}try {if (conn ! null){conn.close();}}catch (Exception se2) {}}}/*** Query data object by primary key ID, mainly used for writing business logic with SQL.* The difference between this method and GetById is that it has an internal caching mechanism.* param T Entity type* param id Object RowID* return Data object*/public T T dolerGet(Object id) {T modelnull;model.getClass();//Class? type T.class;//String typeName type.getSimpleName();//System.out.println(typeName);return null;}///测试SQL生成public T void InsertSqlTest1(){try {T modelnull;Class cmodel.getClass();model(T)c.newInstance();LIS.DAL.ORM.Common.TableInfo tableInfo LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);LIS.DAL.ORM.DBUtility.IDbFactory factory LIS.Core.Context.ObjectContainer.GetTypeObject(LisMianDbFactory);String sql LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(factory, tableInfo, null, null, null, , true);System.out.println(sql);}catch (Exception ex){ex.printStackTrace();}}///测试SQL生成public T void InsertSqlTest(T model){try {//Type type EntityManagerImpl.class.getClass().getGenericSuperclass();//Class c type.getClass();//System.out.println(c.getName());//System.out.println(model.getClass().getName());LIS.DAL.ORM.Common.TableInfo tableInfo LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);LIS.DAL.ORM.DBUtility.IDbFactory factory LIS.Core.Context.ObjectContainer.GetTypeObject(LisMianDbFactory);String sql LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(factory, tableInfo, null, null, null, , true);System.out.println(sql);}catch (Exception ex){ex.printStackTrace();}}/// summary/// 保存对象/// /summary/// typeparam nameT实体类型/typeparam/// param nameentity实体对象/param/// returns影响行数/returnspublic T int Save(T entity){return 0;}
}
实体转Sql的工具类
package LIS.DAL.ORM.Common;
import LIS.Core.CustomAttributes.*;
import LIS.Core.Dto.*;
import LIS.Core.Dto.ParamDto;
import java.util.*;
import java.util.List;
import LIS.DAL.ORM.Common.TableInfo;
import LIS.DAL.ORM.DBUtility.IDbFactory;import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import LIS.DAL.ORM.Common.ColumnInfo;
import LIS.DAL.ORM.Common.TableInfo;
import LIS.Core.Util.ReflectUtil;
import LIS.Core.CustomAttributes.TableAttribute;//通过实体类型得到SQL的工具类
public class ModelToSqlUtil {//通过实体对象得到表信息public static TableInfo GetTypeInfo(Object model) {if (model null) {return null;}try {//返回的对象TableInfo tableInfo new TableInfo();Class c model.getClass();//得到表特性Annotation[] annoList c.getAnnotations();if (annoList ! null annoList.length 0) {for (int i 0; i annoList.length; i) {//表特性if (annoList[i] instanceof TableAttribute) {tableInfo.TableInfo (TableAttribute) annoList[i];}//唯一特性else {tableInfo.UniqueList.add((UniqueAttribute) annoList[i]);}}}//得到列信息Field[] declaredFields c.getDeclaredFields();for (int i 0; i declaredFields.length; i) {LIS.DAL.ORM.Common.ColumnInfo col new LIS.DAL.ORM.Common.ColumnInfo();FrekeyAttribute fk declaredFields[i].getAnnotation(FrekeyAttribute.class);col.FkInfo fk;col.Name declaredFields[i].getName();col.ColType declaredFields[i].getType();col.Value declaredFields[i].get(model);tableInfo.ColList.add(col);}return tableInfo;} catch (Exception ex) {ex.printStackTrace();}return null;}//通过表信息和参数列表组装查询SQL//factory:驱动工厂//tableInfo:表信息//para:参数//operList:参数对应的操作符列表//linkList:多个参数之间连接的操作符 and or这种//orderBySql:Order By的SQL语句//IsFk:是否组装外键查询的SQLpublic static String GetSelectSqlByTableInfo(IDbFactory factory,TableInfo tableInfo, ListParamDto para,ListString operList,ListString linkList, String orderBySql,Boolean IsFk){StringBuilder sbnew StringBuilder();sb.append(select );//是否含有序号列boolean HasSequencefalse;boolean HasSeqNumfalse;//组装查询列for(int i0;itableInfo.ColList.size();i){//存列名String columnName tableInfo.ColList.get(i).Name;if(columnNameSequence){HasSequencetrue;}else if(columnNameSeqNum){HasSeqNumtrue;}//组装查询列if(i0){sb.append(factory.DealPropertyName(columnName));}else{sb.append(,factory.DealPropertyName(columnName));}//组装外键查询信息if(IsFktruetableInfo.ColList.get(i).FkInfo!null) {FrekeyAttribute fkAttrtableInfo.ColList.get(i).FkInfo;String refTableNamefactory.DealTableName(GetTableName(ReflectUtil.GetType(LIS.Model.Entity. fkAttr.Name(), LIS.Model)));sb.append(, (select factory.DealPropertyName(fkAttr.AssociaField()) from refTableName where ti. factory.DealPropertyName(columnName) refTableName . factory.DealPropertyName(fkAttr.RefColumnName()) ) as factory.DealPropertyName(columnName _ fkAttr.Name() _ fkAttr.AssociaField()));//如果有拉取字段1查询拉取字段if (fkAttr.AssociaField1() ! ){sb.append(, (select factory.DealPropertyName(fkAttr.AssociaField1()) from refTableName where ti. factory.DealPropertyName(columnName) refTableName . factory.DealPropertyName(fkAttr.RefColumnName()) ) as factory.DealPropertyName(columnName _ fkAttr.Name() _ fkAttr.AssociaField1()));}//如果有拉取字段2查询拉取字段if (fkAttr.AssociaField2() ! ){sb.append(, (select factory.DealPropertyName(fkAttr.AssociaField2()) from refTableName where ti. factory.DealPropertyName(columnName) refTableName . factory.DealPropertyName(fkAttr.RefColumnName()) ) as factory.DealPropertyName(columnName _ fkAttr.Name() _ fkAttr.AssociaField2()));}}}sb.append( from factory.DealTableName(tableInfo.TableInfo.Name()) ti );//组装查询参数if(para!nullpara.size()0){sb.append( where );for(int i0;ipara.size();i){String oper;if(operList!nulloperList.size()i){operoperList.get(i);}String linkand;if(operList!nulloperList.size()i-1){linkoperList.get(i-1);}if(i0) {sb.append(factory.DealPropertyName(para.get(i).Key.toString()) oper factory.DealSqlPara(para.get(i).Key.toString()));}else{sb.append( link factory.DealPropertyName(para.get(i).Key.toString()) oper factory.DealSqlPara(para.get(i).Key.toString()));}}}//存组装的排序sqlString strSort ;//如果传入了排序字段组装排序语句if (orderBySql ! null orderBySql.length() 0){//用来存处理的排序串String dealStr ;//先分割多个排序条件String[] strList orderBySql.split(,);for (int m 0; m strList.length; m){//分开多个排序条件if (m 0){dealStr ,;}//分开字段名称和升降序String[] strSubList strList[m].split( );//处理字段名称dealStr factory.DealPropertyName(strSubList[0]);//组装处理的串for (int n 1; n strSubList.length; n){dealStr strSubList[n];}}//组装排序串strSort Order By dealStr;}else{if (HasSequence){strSort Order By factory.DealPropertyName(Sequence) ASC;}else if (HasSeqNum){strSort Order By factory.DealPropertyName(SeqNum) ASC;}else{strSort ;}}sb.append(strSort);return sb.toString();}//通过实体类型得到实体表名称private static String GetTableName(Class c){//存表名String strTableName ;//得到表特性TableAttribute tableInfo null;//得到表特性Annotation[] annoList c.getAnnotations();if (annoList ! null annoList.length 0) {for (int i 0; i annoList.length; i) {//表特性if (annoList[i] instanceof TableAttribute) {tableInfo (TableAttribute) annoList[i];strTableNametableInfo.Name();break;}}}return strTableName;}
}
数据库驱动工厂增加得到用户名和密码的方法接口
package LIS.DAL.ORM.DBUtility;//数据驱动层接口ORM基于此加载驱动和执行SQL
public interface IDbFactory {//得到数据库类型String GetStrDbType();//得到数据库连接串String GetConnectionString();//得到数据库用户名String GetUserName();//得到数据库密码String GetUserPass();//得到返回查询的RowID的SQL语句String GetReturnRowIDSql();//处理表名称用来适配不同数据库间的属性命名差异String DealTableName(String tableName);//处理属性名字String DealPropertyName(String propertyName);//DealSqlParaString DealSqlPara(String propertyName);//加载驱动void LoadDriver();
}调用测试这里引入了阿里的对象转JSON库fastjson
package com.company;
//import org.apache.commons.configuration.ConfigurationException;
//import org.apache.commons.configuration.PropertiesConfiguration;
import LIS.Model.Entity.SYSForm;
import LIS.Model.Entity.SYSUser;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
import java.net.URL;
import java.util.List;
import java.util.HashMap;
import java.util.*;
import com.alibaba.fastjson.*;public class Main {public static void main(String[] args) {//用容器的配置xml初始化容器LIS.Core.Context.ObjectContainer.InitIoc();//ORM通过容器取数据库驱动工厂LIS.DAL.ORM.EntityManager.EntityManagerImpl ormnew LIS.DAL.ORM.EntityManager.EntityManagerImpl();//执行查询测试orm.DBSelectTest();//测试通过实体得到SQL语句orm.InsertSqlTest(new SYSForm());orm.InsertSqlTest(new SYSUser());//调用ORM的FindAll测试Hashtable hsnew Hashtable();hs.put(Code,QC);ListSYSForm formListorm.FindAll(new SYSForm(),hs,RowID desc,-1,-1);Object jsonJSONObject.toJSON(formList);System.out.println(查询的LIST数据:json.toString());}
}
测试结果
把依赖的不稳定搞定后就快多了轻松加愉快哈哈。不过发现泛型不如C#强方法不支持默认参数尤其是方法不支持默认参数这个真不像一个现代语言总体使用语法特性方面和工程依赖方面和IDE体验和C#比差多了末日黄花喽官方闭源语法古老