通过自动解除恢复加载动态创建的实体

时间:2011-09-23 07:39:49

标签: hibernate spring jpa entity javassist

我必须使用一个奇怪的数据库结构,在生产中可能会有更多的表但具有相同的列。我们希望使用JPA(Hibernate)来处理它们,通过实体/ JPQL查询。我们的想法是在运行时在JVM中动态地为每个表创建实体类。这种方法很好。我使用Javassist创建实体 - 使用已经存在的编译实体,并动态添加注释(实体,表):

public Class generateGroupStateEntity(String className,String tableName) {
    ClassPool cp = ClassPool.getDefault();
    InputStream is = new FileInputStream(new File("MyTemplateEntity.class"));
    CtClass c = cp.makeClass(is);
    c.setName(className); 
    ClassFile cf = c.getClassFile();
    ConstPool constPool = cf.getConstPool();


    AnnotationsAttribute annotAtr = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
    Annotation annot = new Annotation("javax.persistence.Entity", constPool);
    annotAtr.addAnnotation(annot);

    Annotation annotTable = new Annotation("javax.persistence.Table", constPool);
    annotTable.addMemberValue("name", new StringMemberValue(tableName,cf.getConstPool()));
    annotAtr.addAnnotation(annotTable);

    cf.addAttribute(annotAtr);
    return c.toClass();
  }

当我手工构建Hibernate SessionFactory时,从Configuration对象中,使用addAnnotatedClass方法将这些类添加到Configuration,它可以正常工作。问题在于自动发现,当我在弹簧上下文中使用包扫描时,JPA或AnnotationSessionFactoryBean都不会发现/找到该实体。 (我得到:“QuerySyntaxException:[MyEntity]未映射”异常)

Class.forName(myNewEntityName)的作用意味着它在类加载器中已初始化。

(当然我知道这不是处理这些表的理想设计模式。)

问题是为什么以及如何独占呢?

(Javassist 3.15.0-GA,hibernate core 3.6.6.Final,hibernate-entitymanager 3.5.6-Final)

1 个答案:

答案 0 :(得分:2)

我认为包扫描发生在类路径中的jar和文件夹上 - 而不是在类加载器级别。这是为了优化不将所有类加载到内存中。这个article有一些如何完成的细节。

要解决此问题,您可能需要扩展AnnotationSessionFactoryBean - 并动态添加类列表。