如何解决hibernate组合键异常(期待IdClass映射)?
How to solve hibernate composite key exception (expecting IdClass mapping)?
这个问题以前在这里被问过,但是 none 的解决方案对我有用。
由于 SQL Server 2008 table.
中的复合键,我收到以下错误
java.lang.ExceptionInInitializerError
at HB.Main.<clinit>(Main.java:30)
Caused by: java.lang.IllegalArgumentException: expecting IdClass mapping
at org.hibernate.metamodel.internal.AttributeFactory.resolveMember(AttributeFactory.java:977)
at org.hibernate.metamodel.internal.AttributeFactory.resolveMember(AttributeFactory.java:1035)
at org.hibernate.metamodel.internal.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:450)
at org.hibernate.metamodel.internal.AttributeFactory.buildIdAttribute(AttributeFactory.java:139)
at org.hibernate.metamodel.internal.MetadataContext.buildIdClassAttributes(MetadataContext.java:388)
at org.hibernate.metamodel.internal.MetadataContext.applyIdMetadata(MetadataContext.java:318)
at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.java:221)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:274)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:305)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at HB.Main.<clinit>(Main.java:26)
Exception in thread "main"
我的table看起来像这样
与类的映射如下:
实体 Class
package HB;
import java.util.Objects;
public class EmMonthlyPollTablesEntity
{
private int monthlyPollId;
private int tableId;
public int getMonthlyPollId()
{
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId)
{
this.monthlyPollId = monthlyPollId;
}
public int getTableId()
{
return tableId;
}
public void setTableId(int tableId)
{
this.tableId = tableId;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntity that = (EmMonthlyPollTablesEntity) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode()
{
return Objects.hash(monthlyPollId, tableId);
}
}
ID Class
package HB;
import java.io.Serializable;
import java.util.Objects;
public class EmMonthlyPollTablesEntityPK implements Serializable
{
private int monthlyPollId;
private int tableId;
public EmMonthlyPollTablesEntityPK()
{
}
public EmMonthlyPollTablesEntityPK(int monthlyPollId, int tableId)
{
this.monthlyPollId = monthlyPollId;
this.tableId = tableId;
}
public int getMonthlyPollId()
{
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId)
{
this.monthlyPollId = monthlyPollId;
}
public int getTableId()
{
return tableId;
}
public void setTableId(int tableId)
{
this.tableId = tableId;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntityPK that = (EmMonthlyPollTablesEntityPK) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode()
{
return Objects.hash(monthlyPollId, tableId);
}
}
主要Class
package HB;
import org.hibernate.HibernateException;
import org.hibernate.Metamodel;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import javax.persistence.metamodel.EntityType;
public class Main
{
private static final SessionFactory ourSessionFactory;
static
{
try
{
Configuration configuration = new Configuration();
configuration.setProperty("hibernate.connection.username", "sa");
configuration.setProperty("hibernate.connection.password", "");
configuration.configure();
ourSessionFactory = configuration.buildSessionFactory();
}
catch (Throwable ex)
{
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() throws HibernateException
{
return ourSessionFactory.openSession();
}
public static void main(final String[] args) throws Exception
{
final Session session = getSession();
try
{
System.out.println("querying all the managed entities...");
final Metamodel metamodel = session.getSessionFactory().getMetamodel();
for (EntityType<?> entityType : metamodel.getEntities())
{
try
{
final String entityName = entityType.getName();
final Query query = session.createQuery("from " + entityName);
System.out.println("executing: " + query.getQueryString());
for (Object o : query.list())
{
try
{
System.out.println(" " + o);
}
catch (Exception ex)
{
ex.printStackTrace();
;
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
;
}
}
}
finally
{
session.close();
}
}
}
映射
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="HB.EmMonthlyPollTablesEntity" table="EM_MONTHLY_POLL_TABLES" schema="dbo" catalog="HB2">
<composite-id mapped="true" class="HB.EmMonthlyPollTablesEntityPK">
<key-property name="monthlyPollId">
<column name="MONTHLY_POLL_ID" sql-type="int"/>
</key-property>
<key-property name="tableId">
<column name="TABLE_ID" sql-type="int"/>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
整个 Intellij Idea 项目和 table 脚本可以从 here
下载
Hibernate 中存在错误 composite id's defined via hbm.xml cause java.lang.IllegalArgumentException in JPA deployment
根本原因
在 JPA 中,复合 ID 必须是可嵌入的。因为 EmMonthlyPollTablesEntityPK
class 不可嵌入并且不是 JPA 环境永远不会支持的组件。
解决方案 1:解决方法
在 hibernate.cfg.xml
中禁用元模型填充
<hibernate-configuration>
<session-factory>
<property name="hibernate.ejb.metamodel.population">disabled</property>
<mapping class="..."/>
<!-- ... -->
</session-factory>
</hibernate-configuration>
解决方案 2:删除 HBM 映射并使用注释
据我所知,HBM 映射已被弃用,并将在 Hibernate 的未来版本中删除。
在这种情况下,您可以选择使用 Composite Id
、IdClass
和 EmbeddedId
方法。以下示例使用 EmbeddedId
实体class
@Entity
@Table(name = "EM_MONTHLY_POLL_TABLES")
public class EmMonthlyPollTablesEntity implements Serializable {
@EmbeddedId
private EmMonthlyPollTablesEntityPK id;
@Column(name = "NAME")
private String name;
public EmMonthlyPollTablesEntityPK getId() {
return id;
}
public void setId(EmMonthlyPollTablesEntityPK id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmMonthlyPollTablesEntity)) return false;
EmMonthlyPollTablesEntity that = (EmMonthlyPollTablesEntity) o;
return id.equals(that.id) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
PKclass
@Embeddable
public class EmMonthlyPollTablesEntityPK implements Serializable {
@Column(name = "MONTHLY_POLL_ID", nullable = false)
private int monthlyPollId;
@Column(name = "TABLE_ID", nullable = false)
private int tableId;
public EmMonthlyPollTablesEntityPK() {
}
public EmMonthlyPollTablesEntityPK(int monthlyPollId, int tableId) {
this.monthlyPollId = monthlyPollId;
this.tableId = tableId;
}
public int getMonthlyPollId() {
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId) {
this.monthlyPollId = monthlyPollId;
}
public int getTableId() {
return tableId;
}
public void setTableId(int tableId) {
this.tableId = tableId;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntityPK that = (EmMonthlyPollTablesEntityPK) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode() {
return Objects.hash(monthlyPollId, tableId);
}
}
委托PK的getters和setters当然是可以的。
在这种情况下,您不必禁用元模型填充,您可以从 hibernate.cfg.xml
中删除 HBM 映射资源
虽然我知道将一个巨大的遗留代码库迁移到 JPA 注释和 XML 映射非常累人,但我确信这是可行的方法。
这个问题以前在这里被问过,但是 none 的解决方案对我有用。 由于 SQL Server 2008 table.
中的复合键,我收到以下错误java.lang.ExceptionInInitializerError
at HB.Main.<clinit>(Main.java:30)
Caused by: java.lang.IllegalArgumentException: expecting IdClass mapping
at org.hibernate.metamodel.internal.AttributeFactory.resolveMember(AttributeFactory.java:977)
at org.hibernate.metamodel.internal.AttributeFactory.resolveMember(AttributeFactory.java:1035)
at org.hibernate.metamodel.internal.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:450)
at org.hibernate.metamodel.internal.AttributeFactory.buildIdAttribute(AttributeFactory.java:139)
at org.hibernate.metamodel.internal.MetadataContext.buildIdClassAttributes(MetadataContext.java:388)
at org.hibernate.metamodel.internal.MetadataContext.applyIdMetadata(MetadataContext.java:318)
at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.java:221)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:274)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:305)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at HB.Main.<clinit>(Main.java:26)
Exception in thread "main"
我的table看起来像这样
与类的映射如下: 实体 Class
package HB;
import java.util.Objects;
public class EmMonthlyPollTablesEntity
{
private int monthlyPollId;
private int tableId;
public int getMonthlyPollId()
{
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId)
{
this.monthlyPollId = monthlyPollId;
}
public int getTableId()
{
return tableId;
}
public void setTableId(int tableId)
{
this.tableId = tableId;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntity that = (EmMonthlyPollTablesEntity) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode()
{
return Objects.hash(monthlyPollId, tableId);
}
}
ID Class
package HB;
import java.io.Serializable;
import java.util.Objects;
public class EmMonthlyPollTablesEntityPK implements Serializable
{
private int monthlyPollId;
private int tableId;
public EmMonthlyPollTablesEntityPK()
{
}
public EmMonthlyPollTablesEntityPK(int monthlyPollId, int tableId)
{
this.monthlyPollId = monthlyPollId;
this.tableId = tableId;
}
public int getMonthlyPollId()
{
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId)
{
this.monthlyPollId = monthlyPollId;
}
public int getTableId()
{
return tableId;
}
public void setTableId(int tableId)
{
this.tableId = tableId;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntityPK that = (EmMonthlyPollTablesEntityPK) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode()
{
return Objects.hash(monthlyPollId, tableId);
}
}
主要Class
package HB;
import org.hibernate.HibernateException;
import org.hibernate.Metamodel;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import javax.persistence.metamodel.EntityType;
public class Main
{
private static final SessionFactory ourSessionFactory;
static
{
try
{
Configuration configuration = new Configuration();
configuration.setProperty("hibernate.connection.username", "sa");
configuration.setProperty("hibernate.connection.password", "");
configuration.configure();
ourSessionFactory = configuration.buildSessionFactory();
}
catch (Throwable ex)
{
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() throws HibernateException
{
return ourSessionFactory.openSession();
}
public static void main(final String[] args) throws Exception
{
final Session session = getSession();
try
{
System.out.println("querying all the managed entities...");
final Metamodel metamodel = session.getSessionFactory().getMetamodel();
for (EntityType<?> entityType : metamodel.getEntities())
{
try
{
final String entityName = entityType.getName();
final Query query = session.createQuery("from " + entityName);
System.out.println("executing: " + query.getQueryString());
for (Object o : query.list())
{
try
{
System.out.println(" " + o);
}
catch (Exception ex)
{
ex.printStackTrace();
;
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
;
}
}
}
finally
{
session.close();
}
}
}
映射
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="HB.EmMonthlyPollTablesEntity" table="EM_MONTHLY_POLL_TABLES" schema="dbo" catalog="HB2">
<composite-id mapped="true" class="HB.EmMonthlyPollTablesEntityPK">
<key-property name="monthlyPollId">
<column name="MONTHLY_POLL_ID" sql-type="int"/>
</key-property>
<key-property name="tableId">
<column name="TABLE_ID" sql-type="int"/>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
整个 Intellij Idea 项目和 table 脚本可以从 here
下载Hibernate 中存在错误 composite id's defined via hbm.xml cause java.lang.IllegalArgumentException in JPA deployment
根本原因
在 JPA 中,复合 ID 必须是可嵌入的。因为 EmMonthlyPollTablesEntityPK
class 不可嵌入并且不是 JPA 环境永远不会支持的组件。
解决方案 1:解决方法
在 hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.ejb.metamodel.population">disabled</property>
<mapping class="..."/>
<!-- ... -->
</session-factory>
</hibernate-configuration>
解决方案 2:删除 HBM 映射并使用注释
据我所知,HBM 映射已被弃用,并将在 Hibernate 的未来版本中删除。
在这种情况下,您可以选择使用 Composite Id
、IdClass
和 EmbeddedId
方法。以下示例使用 EmbeddedId
实体class
@Entity
@Table(name = "EM_MONTHLY_POLL_TABLES")
public class EmMonthlyPollTablesEntity implements Serializable {
@EmbeddedId
private EmMonthlyPollTablesEntityPK id;
@Column(name = "NAME")
private String name;
public EmMonthlyPollTablesEntityPK getId() {
return id;
}
public void setId(EmMonthlyPollTablesEntityPK id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmMonthlyPollTablesEntity)) return false;
EmMonthlyPollTablesEntity that = (EmMonthlyPollTablesEntity) o;
return id.equals(that.id) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
PKclass
@Embeddable
public class EmMonthlyPollTablesEntityPK implements Serializable {
@Column(name = "MONTHLY_POLL_ID", nullable = false)
private int monthlyPollId;
@Column(name = "TABLE_ID", nullable = false)
private int tableId;
public EmMonthlyPollTablesEntityPK() {
}
public EmMonthlyPollTablesEntityPK(int monthlyPollId, int tableId) {
this.monthlyPollId = monthlyPollId;
this.tableId = tableId;
}
public int getMonthlyPollId() {
return monthlyPollId;
}
public void setMonthlyPollId(int monthlyPollId) {
this.monthlyPollId = monthlyPollId;
}
public int getTableId() {
return tableId;
}
public void setTableId(int tableId) {
this.tableId = tableId;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EmMonthlyPollTablesEntityPK that = (EmMonthlyPollTablesEntityPK) o;
return monthlyPollId == that.monthlyPollId && tableId == that.tableId;
}
@Override
public int hashCode() {
return Objects.hash(monthlyPollId, tableId);
}
}
委托PK的getters和setters当然是可以的。
在这种情况下,您不必禁用元模型填充,您可以从 hibernate.cfg.xml
虽然我知道将一个巨大的遗留代码库迁移到 JPA 注释和 XML 映射非常累人,但我确信这是可行的方法。