日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用反射和xml配置文件手写一个小型的框架

發布時間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用反射和xml配置文件手写一个小型的框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

通用的增刪改查

  • 1. 利用xml配置實體類和數據庫表名的映射關系
  • 2. 根據xml設計,用正確的數據結構映射類封裝好xml信息
  • 3. 得到數據庫連接前,讀取xml信息,用map封裝成映射數據
  • 4. 寫dao時根據反射和map生成sql語句,拿到屬性值
  • 測試

  • 為了解決上一篇文中實體類的局限性:不可加字段;實體名,表名,列的字段一樣,而且順序一樣
  • 上一篇反射實現dao層增刪改查
  • 本文實現結構

1. 利用xml配置實體類和數據庫表名的映射關系

  • sql語句
create table ticket_info (ticket_id number primary key,ticket_name varchar(30) not null, ticket_price number(10, 2) not null ) create sequence ticket_seqcreate table goods_info (goods_id number primary key, goods_name varchar(30) not null,goods_price number(10, 2) not null,goods_date date not null, goods_factory varchar(50) not null ) create sequence goods_seq
  • xml, 映射表屬性和實體類列

  • goods.xml

<?xml version="1.0" encoding="UTF-8"?><class name="com.lovely.entity.Goods" table="goods_info"><id name="gid" column="goods_id"><sequence>goods_seq</sequence></id><property name="gname" column="goods_name"></property><property name="gprice" column="goods_price"></property><property name="gdate" column="goods_date"></property><property name="gfactory" column="goods_factory"></property> </class>
  • ticket.xml
<?xml version="1.0" encoding="UTF-8"?><!-- 實體類和表之間的映射關系 --> <class name="com.lovely.entity.Ticket" table="ticket_info"> <!-- 類名和表名的映射關系 --><id name="tid" column="ticket_id"> <!-- 實體主鍵和表中主鍵列的映射關系 --><sequence>ticket_seq</sequence></id><property name="tname" column="ticket_name"></property> <!-- 屬性名和表名列的映射關系 --><property name="tprice" column="ticket_price"></property></class>
  • goods, 和 entity的實體類
package com.lovely.entity;import java.sql.Date;public class Goods {private Integer gid;private String gname;private Double gprice;private Date gdate;private String gfactory;public Goods() {}public Integer getGid() {return gid;}public void setGid(Integer gid) {this.gid = gid;}public String getGname() {return gname;}public void setGname(String gname) {this.gname = gname;}public Double getGprice() {return gprice;}public void setGprice(Double gprice) {this.gprice = gprice;}public Date getGdate() {return gdate;}public void setGdate(Date gdate) {this.gdate = gdate;}public String getGfactory() {return gfactory;}public void setGfactory(String gfactory) {this.gfactory = gfactory;}} package com.lovely.entity;public class Ticket {private Integer tid;private String tname;private Double tprice;public Ticket() {}public Ticket(Integer tid, String tname, Double tprice) {super();this.tid = tid;this.tname = tname;this.tprice = tprice;}public Integer getTid() {return tid;}public void setTid(Integer tid) {this.tid = tid;}public String getTname() {return tname;}public void setTname(String tname) {this.tname = tname;}public Double getTprice() {return tprice;}public void setTprice(Double tprice) {this.tprice = tprice;}@Overridepublic String toString() {return "Ticket [tid=" + tid + ", tname=" + tname + ", tprice=" + tprice+ "]\n";}}

2. 根據xml設計,用正確的數據結構映射類封裝好xml信息

  • 主鍵id
package com.lovely.base;public class MapperId {// 實體id 映射 數據庫idprivate String idName;private String idColumn;private String seqName;public String getIdName() {return idName;}public void setIdName(String idName) {this.idName = idName;}public String getIdColumn() {return idColumn;}public void setIdColumn(String idColumn) {this.idColumn = idColumn;}public String getSeqName() {return seqName;}public void setSeqName(String seqName) {this.seqName = seqName;}@Overridepublic String toString() {return "MapperId [idName=" + idName + ", idColumn=" + idColumn+ ", seqName=" + seqName + "]";}}
  • MapperData 映射數據類
package com.lovely.base;import java.util.LinkedHashMap;public class MapperData {// 映射文件類// 實體全類名private String className;// 表名private String tableName;private MapperId mapperId;// 存儲除主鍵外 實體屬性 -> 數據表列 相關信息private LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>();public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public String getTableName() {return tableName;}public void setTableName(String tableName) {this.tableName = tableName;}public MapperId getMapperId() {return mapperId;}public void setMapperId(MapperId mapperId) {this.mapperId = mapperId;}public LinkedHashMap<String, String> getProperties() {return properties;}public void setProperties(LinkedHashMap<String, String> properties) {this.properties = properties;}@Overridepublic String toString() {return "MapperData [className=" + className + ", tableName="+ tableName + ", mapperId=" + mapperId + ", properties="+ properties + "]\n";}}

3. 得到數據庫連接前,讀取xml信息,用map封裝成映射數據

  • 實體屬性名和表的列名一樣,也封裝在map里面了
package com.lovely.dao;import java.io.File; import java.lang.reflect.Field; import java.net.URL; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List;import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;import com.lovely.base.MapperData; import com.lovely.base.MapperId;public class BaseDao {static {try {Class.forName("oracle.jdbc.OracleDriver");} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** key: 全路徑類名 * value: 類和表的映射關系 MapperData*/public static HashMap<String, MapperData> map = new HashMap<String, MapperData>();static {// 靜態塊解析xml映射文件try { Class<?> baseDaoClass = Class.forName("com.lovely.dao.BaseDao");// 得到xml路徑URL url = baseDaoClass.getResource("/com/lovely/mapper");String path = url.getFile();File file = new File(path);// 拿到所有xml文件File[] files = file.listFiles();for (int i = 0; i < files.length; i++) {// 解析xml一個文件// System.out.println(files[i].getName());SAXReader reader = new SAXReader();Document doc = reader.read(files[i]);// 拿到 class結點Element root = doc.getRootElement();MapperData mapperData = new MapperData();// 保存實體類名mapperData.setClassName(root.attributeValue("name")); // 保存數據表名mapperData.setTableName(root.attributeValue("table"));MapperId mapperId = new MapperId();// 主鍵結點映射關系Element primaryKey = root.element("id");// 實體類主鍵mapperId.setIdName(primaryKey.attributeValue("name"));// 表的主鍵mapperId.setIdColumn(primaryKey.attributeValue("column"));// 序列名稱mapperId.setSeqName(primaryKey.elementText("sequence"));// 保存主鍵結點映射關系mapperData.setMapperId(mapperId);@SuppressWarnings("unchecked")// 所有 實體屬性-表名結點映射關系List<Element> property = root.elements("property");LinkedHashMap<String, String> lhm = new LinkedHashMap<String, String>();for (Element field : property) {lhm.put(field.attributeValue("name"), field.attributeValue("column"));}mapperData.setProperties(lhm);// 把實體類 與 xml中的映射數據一一對應map.put(root.attributeValue("name"), mapperData);}} catch (Exception e) {e.printStackTrace();}}static {// 加載沒有配置文件的實體類 try {Class<?> c = BaseDao.class;// mapper下的路徑String path = c.getResource("/com/lovely/entity").getFile();File file = new File(path);File[] files = file.listFiles();for (int i = 0; i < files.length; i++) {String fileName = files[i].getName();String className = "com.lovely.entity." + fileName.substring(0, fileName.indexOf("."));// 沒有映射文件的解析 對于數據庫表名,字段,順序 和 實體的類名 字段 順序一樣。if (!map.containsKey(className)) {// 實體類的類型描述Class<?> cc = Class.forName(className);MapperData value = new MapperData();// 設置實體類名和表名value.setClassName(cc.getName());value.setTableName(cc.getSimpleName());Field[] fields = cc.getDeclaredFields();Field.setAccessible(fields, true);// 拿到主鍵String primaryKeyName = fields[0].getName();MapperId mapperId = new MapperId();mapperId.setIdName(primaryKeyName);mapperId.setIdColumn(primaryKeyName);mapperId.setSeqName("seq_" + cc.getSimpleName());// 屬性 主鍵列名 序列名value.setMapperId(mapperId);LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>();// 設置除主鍵意外的屬性for (int j = 1; j < fields.length; j++) {properties.put(fields[j].getName(), fields[j].getName());}value.setProperties(properties);map.put(className, value);}}} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) {System.out.println(map);}public static Connection getConn() {Connection conn = null;String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";try {conn = DriverManager.getConnection(url, "scott", "scott");} catch (SQLException e) {e.printStackTrace();}return conn;}public static void closeAll(Connection conn, PreparedStatement ps, ResultSet rs) {try {if (rs != null)rs.close();if (ps != null)ps.close();if (conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}} }

4. 寫dao時根據反射和map生成sql語句,拿到屬性值

  • curd實現
package com.lovely.dao;import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set;import com.lovely.base.MapperData; import com.lovely.base.MapperId;/*** * @author echo lovely* * 萬能增刪改查**/ public class CommonDao {public int save(Object entity) {int count = -1;Class<?> c = entity.getClass();MapperData mapperData = BaseDao.map.get(c.getName());StringBuffer sql = new StringBuffer();sql.append("insert into ");sql.append(mapperData.getTableName() + " values (");// insert into tableName values (seq_table.nextval, ?, ?, ?...)sql.append(mapperData.getMapperId().getSeqName() + ".nextval");LinkedHashMap<String,String> properties = mapperData.getProperties();Set<String> keySet = properties.keySet();// 除主鍵外的 實體屬性名for (int i = 0; i < keySet.size(); i++) {sql.append(", ?");}sql.append(")");System.out.println(sql);Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql.toString());// 設置參數的值// 取實體列int index = 1;for (String entityColumn : keySet) {// 反射根據屬性名稱拿值Field field = c.getDeclaredField(entityColumn);field.setAccessible(true);ps.setObject(index, field.get(entity));index ++;}count = ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}return count;}public List<Object> queryAll(Class<?> c) {List<Object> list = new ArrayList<Object>();// 拿到 實體類 與 表的列 映射關系MapperData mapperData = BaseDao.map.get(c.getName());String sql = "select * from " + mapperData.getTableName();Connection conn = BaseDao.getConn();PreparedStatement ps = null;ResultSet rs = null;LinkedHashMap<String, String> properties = mapperData.getProperties();try {ps = conn.prepareStatement(sql);rs = ps.executeQuery();// 表主鍵列名String primaryKeyName = mapperData.getMapperId().getIdColumn();String idName = mapperData.getMapperId().getIdName();while (rs.next()) {Object entity = c.newInstance();Object primaryKeyValue = rs.getObject(primaryKeyName); // 主鍵屬性Field primaryFiled = c.getDeclaredField(idName);if (primaryFiled.getType() == Integer.class)primaryKeyValue = rs.getInt(primaryKeyName);primaryFiled.setAccessible(true);primaryFiled.set(entity, primaryKeyValue);Set<Entry<String,String>> entrySet = properties.entrySet();for (Entry<String, String> entry : entrySet) {// 屬性名稱String filedName = entry.getKey();// 表的列名String columnName = entry.getValue();Object attributValue = rs.getObject(columnName);// System.out.println(filedName + "\t" + columnName + "...");// 除主鍵外的屬性對象Field f = c.getDeclaredField(filedName);if (f.getType() == Double.class) {attributValue = rs.getDouble(columnName);} else if (f.getType() == java.sql.Timestamp.class) {attributValue = rs.getTimestamp(columnName);}f.setAccessible(true);f.set(entity, attributValue);}list.add(entity); }} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, rs);}return list;}public Object queryOne(Object obj) {Object entity = null;Class<?> c = obj.getClass();MapperData mapperData = BaseDao.map.get(c.getName());String sql = "select * from " + mapperData.getTableName() + " where " + mapperData.getMapperId().getIdColumn() + " = ?";System.out.println(sql);Connection conn = BaseDao.getConn();PreparedStatement ps = null;ResultSet rs = null;try {MapperId mapperId = mapperData.getMapperId();ps = conn.prepareStatement(sql);// 拿到主鍵屬性對象Field field = c.getDeclaredField(mapperId.getIdName());field.setAccessible(true);ps.setObject(1, field.get(obj));rs = ps.executeQuery(); LinkedHashMap<String,String> properties = mapperData.getProperties();Set<Entry<String, String>> entrySet = properties.entrySet();if (rs.next()) {// 記得反射創建對象...entity = c.newInstance();Field idFiled = c.getDeclaredField(mapperId.getIdName());idFiled.setAccessible(true);// 取到主鍵值Object idColumn = rs.getObject(mapperId.getIdColumn());System.out.println(idColumn + "\t" + mapperId.getIdName() + "\t" + mapperId.getIdColumn());if (idFiled.getType() == Integer.class) {idColumn = rs.getInt(mapperId.getIdColumn());} idFiled.set(entity, idColumn);for (Entry<String, String> entry : entrySet) {Field f1 = c.getDeclaredField(entry.getKey());f1.setAccessible(true);Object value = rs.getObject(entry.getValue());if (f1.getType() == Double.class)value = rs.getDouble(entry.getValue());else if (f1.getType() == Timestamp.class) {value = rs.getTimestamp(entry.getValue());}f1.set(entity, value); }}} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, rs);}return entity;}public int update(Object entity) {int count = -1;Class<?> c = entity.getClass();StringBuffer sql = new StringBuffer();// 根據類的全路徑 拿到MapperDataMapperData mapperData = BaseDao.map.get(c.getName());// update tabName set * = ?, * = ?, * = ? .... where id = ?sql.append("update " + mapperData.getTableName() + " set ");LinkedHashMap<String,String> properties = mapperData.getProperties();// 除了主鍵外的所有屬性集合Set<String> keySet = properties.keySet();// 數據庫中表 列的集合Collection<String> cloumnNames = properties.values();int cloumnSize = cloumnNames.size();int index = 0;for (String cloumnName : cloumnNames) {if (index < cloumnSize - 1) sql.append(cloumnName + " = ?, ");else sql.append(cloumnName + " = ?");index ++; }sql.append(" where " + mapperData.getMapperId().getIdColumn() + " = ?");System.out.println(sql);Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql.toString());int paramIndex = 1;for (String fieldAttribute : keySet) {// 映射的鍵 -> 實體屬性對象Field field = c.getDeclaredField(fieldAttribute);field.setAccessible(true);Object obj = field.get(entity);ps.setObject(paramIndex, obj);paramIndex ++;}// 主鍵屬性Field field = c.getDeclaredField(mapperData.getMapperId().getIdName());field.setAccessible(true);ps.setObject(paramIndex, field.get(entity));count = ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}return count;}public int delete(Object obj) {int count = -1;Class<?> c = obj.getClass();MapperData mapperData = BaseDao.map.get(c.getName());MapperId mapperId = mapperData.getMapperId();String sql = "delete from " + mapperData.getTableName() + " where " + mapperId.getIdColumn() + " = ?";Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql);// 反射拿到實體類 主鍵屬性對象Field field = c.getDeclaredField(mapperId.getIdName());field.setAccessible(true);// 根據屬性對象 取到 該對象的屬性值ps.setObject(1, field.get(obj));count = ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}return count; }}

測試

  • 一句代碼搞定查詢。。。
package com.lovely.test;import com.lovely.dao.CommonDao; import com.lovely.entity.Student; import com.lovely.entity.Ticket;public class Test1 {public static void main(String[] args) {CommonDao dao = new CommonDao();// 學生類的結構和表的結構一樣System.out.println(dao.queryAll(Studdent.getClass()));// 配置了xml映射關系的System.out.println(dao.queryAll(Ticket.class));}} [Student [sid=46, sname=jack, sgender=male, sbirth=2020-07-02 20:24:01.0, saddress=null, sinfo=null] ] [Ticket [tid=2, tname=花木蘭, tprice=33.2] , Ticket [tid=3, tname=阿凡達2, tprice=50.5] ]

總結

以上是生活随笔為你收集整理的利用反射和xml配置文件手写一个小型的框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。