1. 動態修改注解元凶:
Java代碼
/**
* 對象池工具類
*
* 目前提供ORM動態映射解決方案
*
* @author andy.zheng
* @since 2012.09.25 15:55 PM
* @vesion 1.0
*
*/
public class ClassPoolUtils {
/**
* 運行時動態ORM表映射
*
*
* @param entityClassName 待映射的實體全限定類名
* @param tableName 待映射的表名
* @return 映射后的類對象
*/
public static Class<?> tableMapping(String entityClassName, String tableName){
Class<?> c = null;
if(StringUtils.isEmpty(entityClassName) || StringUtils.isEmpty(tableName)){
throw new IllegalArgumentException("The mapping parameter is invalid!");
}
try {
ClassPool classPool = ClassPool.getDefault();
classPool.appendClassPath(new ClassClassPath(ClassPoolUtils.class));
classPool.importPackage("javax.persistence");
CtClass clazz = classPool.get(entityClassName);
clazz.defrost();
ClassFile classFile = clazz.getClassFile();
ConstPool constPool = classFile.getConstPool();
Annotation tableAnnotation = new Annotation("javax.persistence.Table", constPool);
tableAnnotation.addMemberValue("name", new StringMemberValue(tableName, constPool));
// 獲取運行時注解屬性
AnnotationsAttribute attribute = (AnnotationsAttribute)classFile.getAttribute(AnnotationsAttribute.visibleTag);
attribute.addAnnotation(tableAnnotation);
classFile.addAttribute(attribute);
classFile.setVersionToJava5();
//clazz.writeFile();
//TODO 當前ClassLoader中必須尚未加載該實體。(同一個ClassLoader加載同一個類只會加載一次)
//c = clazz.toClass();
EntityClassLoader loader = new EntityClassLoader(ClassPoolUtils.class.getClassLoader());
c = clazz.toClass(loader , null);
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
public static void main(String[] args) {
Class<?> clazz = ClassPoolUtils.tableMapping("com.andy.model.order.Order", "order1");
System.out.println("修改后的@Table: " + clazz.getAnnotation(Table.class));
}
}
2. PO類加載器:
Java代碼
/**
* 實體類加載器 *
* 該加載器主要用於運行時動態修改實體后,重新裝載實體
*
* @author andy.zheng
* @since 2012.09.25 16:18 PM
* @vesion 1.0
*
*/
public class EntityClassLoader extends ClassLoader {
private ClassLoader parent;
public EntityClassLoader(ClassLoader parent){
this.parent = parent;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return this.loadClass(name, false);
}
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class<?> clazz = this.findLoadedClass(name);
if(null != parent){
clazz = parent.loadClass(name);
}
if(null == clazz){
this.findSystemClass(name);
}
if(null == clazz){
throw new ClassNotFoundException();
}
if(null != clazz && resolve){
this.resolveClass(clazz);
}
return clazz;
}
/**
* @param args
*/
public static void main(String[] args) {
}
}
3. 將最新映射對象交給Hibernate吧~ 當然這個東東當然在Dao層哈,需要覆蓋hibernate初始化默認加載的映射對象。你可以把它正在諸如BaseHiberanteDao中,在需要動態映射表名的時候,先調它一把,然后再寫你的HQL.當然如果接口統一的話,你也可以玩高級一點的。(為需要動態映射的接口代理一下,悄無聲息的動態映射一把!!!可謂是神不知鬼不覺~),
/**
* 運行時動態ORM表映射
*
* @param tableMapping 映射集合
* key - 待映射的表名 value - 待映射的實體對象
*/
@SuppressWarnings("unused")
protected void tableMapping(Map<String, Class<?>> tableMapping){
Assert.notEmpty(tableMapping , "The mapping parameter is empty!");
for (String tableName : tableMapping.keySet()) {
Class<?> entityClass = tableMapping.get(tableName);
String className = entityClass.getName();
ClassMetadata metadata = this.getSessionFactory().getClassMetadata(className);
Class<?> mappedClass = metadata.getMappedClass();
mappedClass = ClassPoolUtils.tableMapping(className, tableName);
}
}
調用例子:
Java代碼
public Page<OrderDetail> getList(int currentPage , int pageSize){
this.tableMapping(new HashMap(){
{
this.put("orderdetail1", OrderDetail.class);
}
});
Page<OrderDetail> page = this.<OrderDetail>pagingList("", currentPage , pageSize);
Assert.notEmpty(page.getItems());
return page;
}
執行語句:
Sql代碼
Hibernate: select count(*) as col_0_0_ from OrderDetail orderdetai0_
Hibernate: select orderdetai0_.id as id15_, orderdetai0_.docid as docid15_, orderdetai0_.ErrorDesc as ErrorDesc15_, orderdetai0_.insertedtime as inserted3_15_, orderdetai0_.OrderID as OrderID15_, orderdetai0_.ordernum as ordernum15_, orderdetai0_.SegmentsIDs as Segments5_15_, orderdetai0_.selltype as selltype15_, orderdetai0_.status as status15_ from OrderDetail orderdetai0_