Java 如何解决hibernate复合键异常(需要IdClass映射)?

Java 如何解决hibernate复合键异常(需要IdClass映射)?,java,hibernate,hibernate-mapping,Java,Hibernate,Hibernate Mapping,这个问题以前在这里被问过,但没有一个解决方案对我有效。 由于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.inte

这个问题以前在这里被问过,但没有一个解决方案对我有效。 由于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" 
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();
    }
}
包装HB;
导入org.hibernate.hibernateeexception;
导入org.hibernate.Metamodel;
导入org.hibernate.Session;
导入org.hibernate.SessionFactory;
导入org.hibernate.cfg.Configuration;
导入org.hibernate.query.query;
导入javax.persistence.metamodel.EntityType;
公共班机
{
私有静态最终会话工厂ourSessionFactory;
静止的
{
尝试
{
配置=新配置();
setProperty(“hibernate.connection.username”、“sa”);
setProperty(“hibernate.connection.password”,“”);
configure.configure();
ourSessionFactory=configuration.buildSessionFactory();
}
捕获(可丢弃的ex)
{
抛出新异常InInitializeRerror(ex);
}
}
公共静态会话getSession()引发HibernateeException
{
返回我们的sessionfactory.openSession();
}
公共静态void main(最终字符串[]args)引发异常
{
最终会话=getSession();
尝试
{
System.out.println(“查询所有托管实体…”);
最终元模型元模型=session.getSessionFactory().getMetamodel();
对于(EntityType EntityType:metamodel.getEntities())
{
尝试
{
最后一个字符串entityName=entityType.getName();
最终查询=session.createQuery(“from”+entityName);
System.out.println(“正在执行:“+query.getQueryString());
对于(对象o:query.list())
{
尝试
{
系统输出打印项次(“+o”);
}
捕获(例外情况除外)
{
例如printStackTrace();
;
}
}
}
捕获(例外情况除外)
{
例如printStackTrace();
;
}
}
}
最后
{
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项目和表格脚本都可以从

下载。Hibernate中有一个bug

根本原因 在JPA中,复合id必须是可嵌入的。因为
EmMonthlyPollTablesEntityPK
类是不可嵌入的,并且它不是一个组件,所以JPA环境永远不会支持它

解决方案1:变通办法 在
hibernate.cfg.xml中禁用元模型填充


残废
解决方案2:删除HBM映射并使用注释 据我所知,HBM映射已被弃用,并将在Hibernate的未来版本中删除

在这种情况下,您可以选择使用
Composite Id
IdClass
embedded Id
方法。下面的示例使用
EmbeddedId

实体类

@实体
@表(name=“EM\U月度调查表”)
公共类EmmonthyPollTablesEntity实现可序列化{
@嵌入ID
私有EmmonthlyPolletablesEntityPK id;
@列(name=“name”)
私有字符串名称;
public-emmonthlypolletablesentitypk getId(){
返回id;
}
public void setId(emmonthlypolletablesentitypk id){
this.id=id;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(!(o EmMonthlyPollTablesEntity的instanceof))返回false;
EmMonthlyPollTablesEntity,该实体=(EmMonthlyPollTablesEntity)o;
return id.equals(that.id)&&
Objects.equals(name,that.name);
}
@凌驾
公共int hashCode(){
返回Objects.hash(id,name);
}
}
PK类

@可嵌入
公共类EmmonthlyPolletableEntityPK实现可序列化{
@列(name=“MONTHLY\u POLL\u ID”,null=false)
私有整数月本币;
@列(name=“TABLE_ID”,null=false)
私有int tableId;
公共每月民意调查表EntityPK(){
}
公共每月轮询表实体类型(int monthlyPollId,int tableId){
this.monthlyPollId=monthlyPollId;
this.tableId=tableId;
}
public int getMonthlyPollId(){
月收益率;
}
public void setMonthlyPollId(int monthlyPollId){
this.monthlyPollId=monthlyPollId;
}
public int getTableId(){
返回tableId;
}
公共void setTableId(int tableId){
this.tableId=tableId;
}
@凌驾
公共布尔等于(对象o){
if(this==o)
返回true;
如果(o==null | | getClass()!=o.getClass())
返回false;
EmMonthlyPollTablesEntityPK,该值=(EmMonthlyPollTablesEntityPK)o;
返回monthlyPollId==that.monthlyPollId&&tableId==that.tableId;
}
@凌驾
公共int hashCode(){
返回Objects.hash(monthlyPollId,tableId);
}
}
委托PK的getter和setter当然是可用的。 在这种情况下,您不必禁用元模型填充,您可以从
hibernate.cfg.xml

虽然我知道将一个巨大的遗留代码库迁移到JPA annot
<?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>