如何在运行时检索JPA中的实体的映射表名称?

时间:2010-02-26 13:57:50

标签: java jpa entity

是否可以确定实体的本机表名称?

如果存在Table注释,则很容易:

entityClass.getAnnotation(Table.class).name()

但如果没有Table注释,那该怎么办?

Hibernate通过Configuration类提供此信息:

configuration.getClassMapping(entityClass.getSimpleName()).getTable().getName()

JPA中有类似内容吗?

5 个答案:

答案 0 :(得分:12)

这是我使用EclipseLink(没有映射文件)的方法:

/**
 * Returns the table name for a given entity type in the {@link EntityManager}.
 * @param em
 * @param entityClass
 * @return
 */
public static <T> String getTableName(EntityManager em, Class<T> entityClass) {
    /*
     * Check if the specified class is present in the metamodel.
     * Throws IllegalArgumentException if not.
     */
    Metamodel meta = em.getMetamodel();
    EntityType<T> entityType = meta.entity(entityClass);

    //Check whether @Table annotation is present on the class.
    Table t = entityClass.getAnnotation(Table.class);

    String tableName = (t == null)
                        ? entityType.getName().toUpperCase()
                        : t.name();
    return tableName;
}

答案 1 :(得分:3)

如果没有表注释(并且没有ORM.xml),那么在JPA中,表名是根据类名形成的(参见JPA规范)。那么为什么你需要一个存取方法?

请参阅http://www.datanucleus.org/products/accessplatform_2_0/jpa/orm/datastore_identifiers.html

答案 2 :(得分:2)

我的一位同事发现了由 Hibernate 支持的 Spring Data JPA 环境的以下解决方案:

import org.hibernate.internal.SessionImpl;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;

@Service
public class EntityClassToTableNameMapper {

    @Transactional
    public String[] getTableNames(EntityManager em, Class entityClass) {

        Object entityExample;
        try {
            entityExample = entityClass.newInstance();
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }

        SessionImpl session = em.unwrap(SessionImpl.class);

        EntityPersister persister = session.getEntityPersister(null, entityExample);

        if (persister instanceof AbstractEntityPersister) {
            AbstractEntityPersister persisterImpl = (AbstractEntityPersister) persister;

            String tableName = persisterImpl.getTableName();

            String rootTableName = persisterImpl.getRootTableName();

            return new String[] {rootTableName, tableName};

        } else {
            throw new RuntimeException("Unexpected persister type; a subtype of AbstractEntityPersister expected.");
        }
    }
}

答案 3 :(得分:1)

如果您使用@Table注释,则没有问题,如您所示。如果您不使用该注释,则表名与类名相同(JPA默认值)。

如果您使用映射文件,您需要解析它并重新检索表名,这很有趣 - 这不是很困难,但需要一些工作。如果您害怕性能问题,那么您可以解析映射文件一次并缓存所有表名。

答案 4 :(得分:0)

询问底层ORM的元模型是最可靠的:查看@Table的存在是不够的,不仅可以通过XML配置(例如orm.xml)覆盖它,而且使用JOINED策略, @Table可能是一个超级班。