【问题标题】:How to solve hibernate composite key exception (expecting IdClass mapping)?如何解决hibernate复合键异常(期望IdClass映射)?
【发布时间】:2019-12-24 11:51:02
【问题描述】:

这个问题以前在这里被问过,但没有一个解决方案对我有用。 由于我的 SQL Server 2008 表中的复合键,我收到以下错误。

java.lang.ExceptionInInitializerError
    at HB.Main.<clinit>(Main.java:30)
Caused by: java.lang.IllegalArgumentException: expecting IdClass mapping
    at org.hibernate.metamodel.internal.AttributeFactory$3.resolveMember(AttributeFactory.java:977)
    at org.hibernate.metamodel.internal.AttributeFactory$5.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" 

我的桌子是这样的

类和映射如下: 实体类

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 类

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);
    }
}

主类

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 Project 和表格脚本可以从here下载

【问题讨论】:

  • 为什么要同时使用XML和注解?
  • 此代码由 Intellij Idea 向导生成。它可以选择两者都做。我试过不加注释也得到相同的结果。
  • 首先,决定一种配置方式——XML 或注解。删除与另一个相关的所有内容。然后在这里显示剩余的部分。这样就更容易理解您的问题并为您提供帮助。
  • 好的,我已经切换到仅映射方法。

标签: java hibernate hibernate-mapping


【解决方案1】:

Hibernate composite id's defined via hbm.xml cause java.lang.IllegalArgumentException in JPA deployment有一个bug

根本原因

在 JPA 中,复合 id 必须是可嵌入的。因为EmMonthlyPollTablesEntityPK 类是不可嵌入的并且它不是一个组件,所以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 IdIdClassEmbeddedId 方法。以下示例使用EmbeddedId

实体类

@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);
    }
}

PK类

@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 的getter 和setter。 在这种情况下,您不必禁用元模型填充,您可以从 hibernate.cfg.xml 删除 HBM 映射资源

虽然我知道将庞大的遗留代码库迁移到 JPA 注释和 XML 映射非常费力,但我确信这是要走的路。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2012-10-07
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多