在运行时中检索JPA中实体的表名的代码示例?

时间:2014-02-07 14:26:09

标签: class jpa annotations entity

我想列出我的JPA实体模型的所有数据库表名称,但是我无法获得正确的实体类!

EntityManagerFactory factory;
Set<EntityType<?>> entities = factory.getMetamodel().getEntities();
for (EntityType entity: entities) {
    String tableName = entity.getClass().getAnnotation(Table.class).name();
    logger.debug("Entity name  = {}", entity.getName(); //This works
    logger.debug("Entity class = {}", entity.getClass().getName()); //This returns the runtime class of the object, and not the entity class!!
    logger.debug("Entity table = {}", entity.getClass().getAnnotation(Table.class).name()); //Nothing, because it does not find the correct class
}

输出:

Entity name  = PersonEntity
Entity class = org.hibernate.jpa.internal.metamodel.EntityTypeImpl
Entity table = ........ nothing, because this works on the EntityTypeImpl and not on the PersonEnity

如何获取实体类的表名?

2 个答案:

答案 0 :(得分:1)

好的,所以如果想用反射来做这件事。它应该很简单,因为这个运行时类必须扩展你的类。如果它不会扩展您的课程,您将无法在您的应用程序中使用它。

所以你必须做类似下面的事情

    String myPackage = "com.company.";
    Class entityClass = y.getClass();
    while (!entityClass.getCanonicalName().startsWith(myPackage)) {
        entityClass = entityClass.getSuperclass();
    }
    Class classInYourPackage = entityClass;

你应该得到正确的(你的)课程。

未经测试,但这是它应该工作的方式。

编辑:不确定JPA将为这些运行时类分配什么包。因此,如果上面的代码不起作用,请尝试使用getSuperclass()方法。

答案 1 :(得分:1)

要回答这个问题,我们必须意识到JPA运行时类型包装了原始的@Entity注释POJO。使用非运行时类的简单测试将显示表名称是可访问的:

System.out.println("Table_Name: " + MyEntity.class.getAnnotation(Table.class).name());

所以这里的技巧是访问正确的实体类引用,然后从那里调用所需的函数。

参考EntityTypeImpl的API,我们可以看到它继承自AbstractType,它提供了方法&#34; getJavaType()&#34;,它返回对底层的引用实体类。有了这些知识,我们可以编写以下函数来获取与当前会话关联的每个实体类,以及与每个实体关联的每个Table名称。

protected void testFunc() {
    Metamodel metamodel = entityManager.getMetamodel();
    for (EntityType<?> e : metamodel.getEntities()) {
        Class<?> entityClass = e.getJavaType();
        String entityTableName = entityClass.getAnnotation(Table.class).name();
        System.out.println("Table_Name: " + entityTableName);
    }
}