前面贴出的《运行时动态修改注解》,好多同志私信于我表示不知道该怎么用?觉得有必要再谈一把~
在前篇文章中,提出了怎样动态修改注解的解决方案,需要说明的是更适用于POJO动态映射的范围较小的情况。(POJO需要动态映射的表结构相同表名不同这个范围就比较小,或者增加修改某个属性。。。),如果整个对象需要动态映射不同结构的表,那就完全没必要了!倒是可以做到,却没什么意义。相当于一个POJO通吃~ 如果需要动态映射的范围太大,你就需要考虑是否是你方案的问题了-- 有必要用憨包儿呢特吗?!一般来说映射的东西是配置性的,初始化时就定了。我们动态映射已经违背常伦咯 搞太多的特殊化,还是不好的! 因此我就只动态映射表名,呵呵。。。
下面咱们来说说咋个特殊化哈~ 注意咯
1. 动态修改注解元凶:
/**
* 对象池工具类
*
* 目前提供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类加载器:
/**
* 实体类加载器
*
* 该加载器主要用于运行时动态修改实体后,重新装载实体
*
* @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);
}
}
调用例子:
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;
}
执行语句:
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_
分享到:
相关推荐
源码追踪是软件开发中的重要技能,尤其是在调试和优化代码时。这份名为“源码追踪经验谈”的PDF文档,很可能是某位资深开发者或者技术专家根据自己的实践经历编写的,旨在分享他们在源码分析和调试过程中的技巧和...
2. **添加注释**:在代码中加入必要的注释,不仅可以帮助自己和其他开发者更好地理解代码意图,还能在后期修改或调试时提供参考。 3. **显式声明和引用对象**:使用`Dim`语句明确声明变量,避免拼写错误导致的新...
在尝试使用jQuery的`attr`方法动态修改`enctype`属性时,例如: ```javascript $('form').attr('enctype', 'multipart/form-data'); ``` 在大多数现代浏览器中,这种方法是有效的。但不幸的是,旧版的Internet ...
总之,Java反射机制是Java平台的强大功能,它允许程序在运行时动态地访问和修改类的行为。理解并熟练掌握反射机制,将有助于编写出更加灵活、强大的代码。不过,由于其潜在的安全性和性能问题,使用时应谨慎权衡。...
此外,PowerBuilder还支持脚本语言PBL,使得在运行时动态修改应用程序的行为成为可能。 在进行PowerBuilder开发时,应注重代码的结构和可维护性。使用类(Class)组织代码,可以实现代码复用和模块化,提高程序的可...
将它注释起来逐渐地优化,足够了即可保留所有的工作版本从编码到调试:空白是好的使用有意义的变量名不要重复使用变量逐步细化在写代码之前先写注释有可能的话尽量避免使用指针避免使用麻烦的动态存:静态地分配所有...
《ppk谈JavaScript》系列是JavaScript领域的经典读物,作者ppk(Peter-Paul Koch)是一位知名的前端开发者和浏览器兼容性专家。在这个部分,我们聚焦于JavaScript的核心概念、语法以及在实际开发中的应用。 首先,...
在没有外部晶振时,应取消或注释掉这一定义,确保系统使用内部HSI。 总结来说,STM32F103和STM32F030的时钟管理涉及多个层面,包括选择合适的时钟源、配置PLL、切换时钟源以及调整系统配置。理解和熟练掌握这些知识...
- 动态创建类或方法,实现运行时的类修改或扩展。 使用反射机制时,开发者需要特别注意,因为它可能会降低程序的性能,并且在一定程度上破坏封装性。因此,反射通常建议在没有其他替代方案的情况下使用,或者用在...
* 我们可以放心地在 VI 的前面板(对于非界面 VI)和框图里添加图片、注释等信息来帮助编写、维护 LabVIEW 程序,这些帮助信息不会在 VI 运行时占用内存。 二、内存泄漏 LabVIEW 与 C 语言不同,它没有任何分配或...
该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码...
该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码...
该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码...
在创建一个空的测试项目时,QTP提供了“Record and Run Setting”功能,允许用户设置录制和运行的参数。通过此设置,用户可以指定QTP在录制过程中应如何交互和访问目标应用程序。在开始录制前,确保已配置好这些设置...
### JavaWeb项目开发个人常见问题与经验浅谈 #### 一、业务逻辑 在JavaWeb项目的开发过程中,业务逻辑的设计尤为重要。它不仅关系到系统的稳定性,还直接影响用户体验和项目的后期维护成本。 - **对基础资料的...
同时,编写清晰的文档和注释,以便于其他开发者理解和修改代码。此外,开发者还应遵循良好的编程规范,采用模块化设计,使得软件的维护和扩展变得更加容易。 2.2 实施系统化的维护流程 建立一套完善的软件维护流程...
- 或者修改`conf/server.xml`配置文件,添加`<Context>`标签,指定应用程序路径。 二、使用 JSP 实现输出 1. **JSP 概述**: JSP是一种基于Java的服务器端脚本语言,用于生成动态HTML、XML或其他格式的文档。它...
- **清晰的注释**:为代码添加注释可以帮助理解脚本的目的和每个部分的作用,方便后期维护和调试。 - **模块化设计**:将复杂脚本分解为多个函数,便于测试和调试每个独立部分。 - **错误处理**:使用`if`语句...
《浅谈更新Linux-3.2.5:内核配置与编译详解》 Linux内核的更新和移植是一项技术性极强的工作,对于开发者来说,理解和掌握这一过程至关重要。本文将聚焦于Linux-3.2.5内核的配置和编译,以帮助读者深入理解如何将...