How to retrieve mapping table name for an entity in JPA at runtime?

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


How to retrieve mapping table name for an entity in JPA at runtime?



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:


Configuration


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



Is there something similar in JPA?





as far as i know this is indeed not part of the standard API, so you will have to rely on the actual implementation (hibernate, toplink, ...) to get what you want
– Stefan De Boey
Feb 26 '10 at 14:40




5 Answers
5



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 ?



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





I wanted to avoid implementing the algorithm again. And I wanted to avoid parsing the XML mapping file, too. But I already thought, there would be no way to ask the JPA implementation for the real table names. Thanks a lot.
– marabol
Mar 1 '10 at 9:14





You can override the name using the orm.xml file so programatically re-doing the algorithm also needs to read in the correct orm file.
– Καrτhικ
Apr 18 '14 at 20:17





Link is dead...
– Alex Burdusel
Aug 3 '15 at 8:24





Link is not working
– CrazyJavaLearner
Sep 27 '16 at 9:09



This is the method I am using with EclipseLink (no mapping file):


/**
* 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;
}





Don't think it's a correct way, e.g. what the method would return for the entity with name SomeComplexName?
– skwisgaar
Jan 11 at 11:08





@skwisgaar SOMECOMPLEXNAME in case there is no @Table annotation on the entity. Otherwise the name specified via the @Table annotation.
– Daniel Szalay
Jan 11 at 13:42




SOMECOMPLEXNAME


@Table


name


@Table





afaik default behavior is to map camelcased entities to snakecased tables (e.g. SomeComplexName -> some_complex_name). I might be wrong though :)
– skwisgaar
Jan 11 at 14:02





@skwisgaar I just tried it with Hibernate, the entity name got uppercased
– Daniel Szalay
Jan 11 at 15:07





yes, same for me (mean, when I ran the code sample) but my tables have snakecased names so I ended up splitting it by uppercase letter and joining with underscore: String tableName = String.join("_", entity.getClass().getSimpleName().split("(?=\p{Upper})"));. It's far from perfect but it's enough for my pretty simple case (I use it in tests).
– skwisgaar
Jan 11 at 15:14




String tableName = String.join("_", entity.getClass().getSimpleName().split("(?=\p{Upper})"));



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).



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.



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.





This is more a comment.
– jogo
Feb 13 '16 at 20:07



A colleague of mine found the following solution for a Spring Data JPA environment backed by 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.");
}
}
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

lHc HI9te6xefDdOSu4iVtF0B7N7,4,ePOuZz NSagp,iOwWINNfDONTLh,Ca,Ml
uOLLudUFEugJjurXMGAv6,PD3r2bM35 7AqHe2yjc,Du82LSW we T,xQudYqlqRVUrUWaFEY3FgkLR9AE2f,kX3q

Popular posts from this blog

Visual Studio Code: How to configure includePath for better IntelliSense results

Spring cloud config client Could not locate PropertySource

Current 93