Java 如何在运行时检索 JPA 中实体的映射表名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2342075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to retrieve mapping table name for an entity in JPA at runtime?
提问by marabol
Is it possible to determine the native table name of an entity?
是否可以确定实体的本机表名?
If a Table
annotation is present it's easy:
如果存在Table
注释,则很容易:
entityClass.getAnnotation(Table.class).name()
But what about if no Table
annotation is present?
但是如果没有Table
注释呢?
Hibernate provides this information via the Configuration
class:
Hibernate 通过Configuration
类提供此信息:
configuration.getClassMapping(entityClass.getSimpleName()).getTable().getName()
Is there something similar in JPA?
JPA中有类似的东西吗?
采纳答案by DataNucleus
If no table annotation is present (and no ORM.xml) then in JPA the table name is formed based on the class name (see the JPA spec). Hence why exactly do you need an accessor method ?
如果没有表注释(并且没有 ORM.xml),那么在 JPA 中,表名是基于类名形成的(请参阅 JPA 规范)。因此,您究竟为什么需要访问器方法?
See http://www.datanucleus.org/products/accessplatform_2_0/jpa/orm/datastore_identifiers.html
请参阅http://www.datanucleus.org/products/accessplatform_2_0/jpa/orm/datastore_identifiers.html
回答by Piotr Kochański
If you use @Table annotation, there is no problem, as you have shown. If you don't use that annotation, then table name is the same as the class name (JPA default).
如果您使用@Table 注释,则没有问题,如您所示。如果您不使用该注释,则表名与类名相同(JPA 默认)。
The fun starts if you use mapping file, you need to parse it and retrive table name - this is not very difficult, but demands some work. If you are afraid of performance issues then you can parse mapping file(s) once and cache all tables names.
如果您使用映射文件,乐趣就开始了,您需要解析它并检索表名 - 这不是很困难,但需要一些工作。如果您害怕性能问题,那么您可以解析一次映射文件并缓存所有表名。
回答by Daniel Szalay
This is the method I am using with EclipseLink (no mapping file):
这是我与 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;
}
回答by p3consulting
Asking to the meta-model of the underlaying ORM is the most reliable: looking at the presence of the @Table is not enough, not only it can be overridden by XML configuration (e.g. orm.xml) but with JOINED strategy, the @Table may be on a super-class.
询问底层 ORM 的元模型是最可靠的:查看 @Table 的存在是不够的,不仅它可以被 XML 配置(例如 orm.xml)覆盖,而且使用 JOINED 策略,@Table可能是超班。
回答by Karmakulov Kirill
A colleague of mine found the following solution for a Spring Data JPAenvironment backed by Hibernate:
我的一位同事为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.");
}
}
}