我们是否有可能以编程方式找到Hibernate实体的主键字段(类似于JPA的PersistenceUnitUtil
)?
答案 0 :(得分:8)
SessionFactory
提供了一个名为getClassMetadata()的方法来获取类的元数据对象(即ClassMetadata)
要获取实体的标识符属性的名称,请使用ClassMetadata.getIdentifierPropertyName()
ClassMetadata employeeMeta = sessionFactory.getClassMetadata(Employee.class);
System.out.println("Name of the identifier property of the employee entity :" + employeeMeta .getIdentifierPropertyName());
要获取托管实体实例的标识符属性的值,请使用ClassMetadata.getIdentifier(Object entity, SessionImplementor session)
例如: 假设您有一个从会话加载的托管实体实例:
List<Employee> employeeList = (List<Employee>)session.createQuery("from Employee where gender ='F'").list();
ClassMetadata employeeMeta = session.getSessionFactory().getClassMetadata(Employee.class);
for (Employee employee : employeeList ) {
System.out.println("Value of the Primary key:" + employeeMeta.getIdentifier(employee , session) );
}
答案 1 :(得分:3)
查看PersistentClass
(您可以使用configuration.getClassMapping(<classname>)
获得)。根据您的需要,getIdentifierProperty()
或getKeyClosureIterator()
可能会有用。
答案 2 :(得分:3)
我意识到这个问题现在已经有两年多的时间了,已经回答了,但它介于Google发现的“hibernate获取主键字段”(可能还有其他类似查询)的前10个结果之间,所以我认为添加这些信息非常重要这里。
最近,我正在研究Java系统,我需要获取表的主键,但是,我所拥有的只是Hibernate Configuration
对象和表的名称。
虽然Johanna的回答非常简单并且帮助了我,但我发现它对于具有复合主键的表没有预期效果,因为只找到组成主键的一个字段。
我挖掘了PersistentClass
属性并找到了处理主键(复合和单一)两种情况的方法:
/**
* Maps a table's primary key to a Map<String, String> where the keys are the names of
* the fields that compose the primary key and the values are the type names of said
* fields.
*
* @param tableName The name of the which for which the primary keys will be gotten
* @param hibernateConfiguration The Hibernate configuration for the database
* IMPORTANT: $tableName must be already mapped in the configuration.
* @returns A map with the fields names as keys and their types' names as values.
*/
public static Map<String, String> retrievePrimaryKeys(String tableName, Configuration hibernateConfiguration) {
hibernateConfiguration.buildMappings();
HashMap<String, String> primaryKeys = new HashMap<>();
PersistentClass tableMapping = hibernateConfiguration.getClassMapping(tableName);
Object tableIdentifier = tableMapping.getIdentifier();
if(tableIdentifier instanceof SimpleValue) {
// Whenever the identifier is a SimpleValue, it means that the table has only one PrimaryKey.
// At this point, it's assumed that the primary key was mapped using the <id> element in the mapping XML file.
// We iterate over the columns below, because it's a safer way of handling this thing.
SimpleValue tableIdentifierValue = (SimpleValue) tableIdentifier;
Iterator primaryKeysIterator = tableIdentifierValue.getColumnIterator();
while(primaryKeysIterator.hasNext()) {
Column primaryKey = (Column) primaryKeysIterator.next();
SimpleValue primaryKeyValue = (SimpleValue) primaryKey.getValue();
primaryKeys.put(primaryKey.getName(), primaryKeyValue.getTypeName());
}
}
else if (tableIdentifier instanceof Component)
{
// Whenever the identifier is a Component, it means that the table has a composite primary key.
// At this point, it's assumed that the primary key was mapped using the <composite-id> element in the mapping XML file
Component identifiers = (Component) tableIdentifier;
Iterator identifierIterator = identifiers.getPropertyIterator();
while(identifierIterator.hasNext()) {
Property identifier = (Property) identifierIterator.next();
SimpleValue value = (SimpleValue) identifier.getValue();
primaryKeys.put(identifier.getName(), value.getTypeName());
}
}
else
{
// If the program reaches this point, it means that Hibernate hates you and there's a third unknown way of declaring and getting a table's primary key.
}
return primaryKeys;
}
我必须补充一点,Java不是我的专长,因为Hibernate都不是,所以可能是一种更好,更简洁的处理方式(我希望至少如此),但我可以找不到。