This question has been asked here before but none of the solutions are working for me. I am getting following error due to composite key in my 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$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"
my table looks like this
The classes and mapping is as follows: Entity 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);
}
}
Main 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();
}
}
}
Mapping
<?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>
Entire Intellij Idea Project and table script can be downloaded from here
There is a bug in Hibernate composite id's defined via hbm.xml cause java.lang.IllegalArgumentException in JPA deployment
In JPA the composite id must be embeddable. Because the EmMonthlyPollTablesEntityPK
class is not embeddable and that is not a component the JPA environment will never support that.
Disable metamodel population in hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.ejb.metamodel.population">disabled</property>
<mapping class="..."/>
<!-- ... -->
</session-factory>
</hibernate-configuration>
As I know HBM mappings are deprecated and will be removed in a future version of Hibernate.
In this case you can choose between using Composite Id
, IdClass
and EmbeddedId
approaches. The following example uses EmbeddedId
Entity 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);
}
}
PK class
@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);
}
}
Delegating PK's getters and setters are available of course.
In this case you don't have to disable metamodel population and you can drop HBM mapping resource from hibernate.cfg.xml
Although I know migrating a huge legacy codebase to JPA annotations and XML mappings is very exhausting I'm sure that is the way to go.