Question

I have to work with a strange DB structure, where on production there could be more tables but with same columns. And we want to use JPA (Hibernate) with handle them, by entities/JPQL queries. The idea is to create entity classes for each table dynamically within JVM at runtime. This approach works fine. I create Entities with Javassist - using an already existing compiled entity, and I add annotations to it dynamically (Entity, Table):

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();
  }

When I build a Hibernate SessionFactory by hand, from a Configuration object, adding this classes using addAnnotatedClass method to Configuration, it works fine. Problem is with automated discovery, the entity is not discovered/found neither by JPA, or by AnnotationSessionFactoryBean - when I use package scanning with within a spring context. (I get: "QuerySyntaxException: [MyEntity] is not mapped" exception)

Class.forName(myNewEntityName) works that means the it is Initialized within the Classloader.

(Of course I know this is not an Ideal design patter for Handling these tables.)

The question is why and how to sole it?

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

Was it helpful?

Solution

I think package scanning happens on the jars and folder in the classpath - not at the classloader level. This is to optimize not loading all the classes into memory. This article has some details of how it is done.

To solve it you might have to extend the AnnotationSessionFactoryBean - and add the list of classes dynamically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top