【原創】基於註解運行時動態ORM映射

因爲當前項目採用了分表策略,故一個實體會對應多個相同結構的表。只是映射的表名不同而已~項目又使用憨包兒呢特(Hibernate),讓我採用原生SQL總感受不是那麼爽,咋辦呢?!第一念頭就是若是可以動態映射就好啦,也就是如今想查table1只需將實體對應的 table映射爲table1便可。咋個實現動態映射呢?!也就是須要動態改變類的註解。又咋個可以動態改變類的註解呢?!本質上修改字節碼,從新加載類便可,也就是所謂的字節碼加強功能~  看都看不懂字節碼咋個修改呢?!仍是須要站在巨人的肩上才行。ASM以及JDK自帶的字節碼加強都不用,立刻想到CGlib,javassist。。。仍是痛苦的折騰了良久,爲了你們不走個人彎路~ 直接上代碼先~css

動態映射代碼以下:html

 1: public class ClassPoolUtils {
 2: 
 3: 
 4:     /**
 5:  * 動態ORM映射
 6:  * 
 7:  * @param entityClassName 待映射的實體全限定類名
 8:  * @param tableName 待映射的表名
 9:  * @return 映射後的類對象
 10:  */
 11:     public static Class<?> tableMapping(String entityClassName, String tableName){
 12:         Class<?> c = null;
 13:         try {
 14:             ClassPool classPool = ClassPool.getDefault();
 15:             classPool.appendClassPath(new ClassClassPath(ClassPoolUtils.class));
 16:             classPool.importPackage("javax.persistence");
 17:             CtClass clazz = classPool.get(entityClassName);
 18:             ClassFile classFile = clazz.getClassFile();
 19: 
 20:             System.out.println("加強前Entity01:" + clazz.getAnnotation(Entity.class));
 21:             System.out.println("加強前Table02:" + clazz.getAnnotation(Table.class));
 22: 
 23:             ConstPool constPool = classFile.getConstPool();
 24:             Annotation tableAnnotation = new Annotation("javax.persistence.Table", constPool);
 25:             tableAnnotation.addMemberValue("name", new StringMemberValue(tableName, constPool));
 26:             // 獲取運行時註解屬性
 27:             AnnotationsAttribute attribute = (AnnotationsAttribute)classFile.getAttribute(AnnotationsAttribute.visibleTag);
 28:             attribute.addAnnotation(tableAnnotation);
 29:             classFile.addAttribute(attribute);
 30:             classFile.setVersionToJava5();
 31:             //clazz.writeFile();
 32: 
 33:             System.out.println("加強後Entity001:" + clazz.getAnnotation(Entity.class));
 34:             System.out.println("加強後Table002:" + clazz.getAnnotation(Table.class));
 35:             //TODO 當前ClassLoader中必須還沒有加載該實體。(同一個ClassLoader加載同一個類只會加載一次)
 36:             c = clazz.toClass();
 37:             System.out.println("加強後toClass-Entity0001:" + c.getAnnotation(Entity.class));
 38:             System.out.println("加強後toClass-Table0002:" + c.getAnnotation(Table.class));
 39:         } catch (Exception e) {
 40:             e.printStackTrace();
 41:         }
 42: 
 43:         return c;
 44:     }
 45:  
 46:     public static void main(String[] args) {
 47:           ClassPoolUtils.tableMapping("com.andy.model.Order", "order1");
 48:     }

執行結果:java

 1: 加強前Entity01:@javax.persistence.Entity
 2: 加強前Table02:null
 3: 加強後Entity001:@javax.persistence.Entity
 4: 加強後Table002:@javax.persistence.Table(name="order1")
 5: 加強後toClass-Entity0001:@javax.persistence.Entity(name=)
 6: 加強後toClass-Table0002:@javax.persistence.Table(schema=, catalog=, uniqueConstraints=[], name=order1)
相關文章
相關標籤/搜索