Как получить имя таблицы сопоставления для сущности в JPA во время выполнения? - PullRequest
26 голосов
/ 26 февраля 2010

Можно ли определить собственное имя таблицы сущности?

Если присутствует аннотация Table, это просто:

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

Но что делать, если нет Table аннотации?

Hibernate предоставляет эту информацию через Configuration класс:

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

Есть ли что-то похожее в JPA?

Ответы [ 5 ]

13 голосов
/ 17 октября 2014

Это метод, который я использую с 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;
}
3 голосов
/ 27 февраля 2010

Если нет табличной аннотации (и нет ORM.xml), то в JPA имя таблицы формируется на основе имени класса (см. Спецификацию JPA). Следовательно, зачем вам нужен метод доступа?

См. http://www.datanucleus.org/products/accessplatform_2_0/jpa/orm/datastore_identifiers.html

2 голосов
/ 27 июля 2018

Мой коллега нашел следующее решение для среды Spring Data JPA , поддерживаемой Hibernate :

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.");
        }
    }
}
1 голос
/ 26 февраля 2010

Если вы используете аннотацию @Table, проблем, как вы показали, нет. Если вы не используете эту аннотацию, тогда имя таблицы совпадает с именем класса (JPA по умолчанию).

Веселье начинается, если вы используете файл сопоставления, вам нужно проанализировать его и получить имя таблицы - это не очень сложно, но требует некоторой работы. Если вы боитесь проблем с производительностью, то можете один раз проанализировать файлы сопоставления и кэшировать все имена таблиц.

0 голосов
/ 13 февраля 2016

Обращение к метамодели лежащего в основе ORM является наиболее надежным: недостаточно посмотреть на наличие @Table, его можно не только переопределить конфигурацией XML (например, orm.xml), но и с помощью стратегии JOINED, @Table может быть в суперклассе.

...