java - query - ¿Cómo recuperar el nombre de la tabla de asignación para una entidad en JPA en tiempo de ejecución?
jpql java example (5)
Este es el método que estoy usando con EclipseLink (sin archivo de mapeo):
/**
* 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;
}
¿Es posible determinar el nombre de la tabla nativa de una entidad?
Si hay una anotación en la Table
es fácil:
entityClass.getAnnotation(Table.class).name()
Pero, ¿qué pasa si no hay una anotación de Table
presente?
Hibernate proporciona esta información a través de la clase de Configuration
:
configuration.getClassMapping(entityClass.getSimpleName()).getTable().getName()
¿Hay algo similar en JPA?
Pedir al metamodelo del ORM subyacente es lo más confiable: considerar la presencia del @Table no es suficiente, no solo se puede anular mediante la configuración XML (por ejemplo, orm.xml), sino que con la estrategia UNIDA, el @Table puede estar en una súper-clase.
Si no hay una anotación de tabla presente (y no hay ORM.xml), entonces en JPA, el nombre de la tabla se forma en función del nombre de la clase (consulte la especificación de JPA). Entonces, ¿por qué exactamente necesitas un método de acceso?
Ver http://www.datanucleus.org/products/accessplatform_2_0/jpa/orm/datastore_identifiers.html
Si usa la anotación @Table, no hay ningún problema, como lo ha demostrado. Si no usa esa anotación, el nombre de la tabla es el mismo que el nombre de la clase (valor predeterminado de JPA).
La diversión comienza si usa el archivo de mapeo, necesita analizarlo y recuperar el nombre de la tabla; esto no es muy difícil, pero exige algo de trabajo. Si tiene miedo de los problemas de rendimiento, puede analizar los archivos de asignación una vez y almacenar en caché todos los nombres de las tablas.
Un colega mío encontró la siguiente solución para un entorno Spring Data JPA respaldado por 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.");
}
}
}