Olá, estou tentando fazer um relacionamento many-to-many com um atributo na tabela de join e há um erro me perseguindo. Segui a doc do Hibernate e fiz o seguinte:
Classe que representa o relacionamento com um atributo:
[code]public class RelationshipPurchaseGoods implements Serializable {
/**
*
*/
private Goods goods;
/**
*
*/
private int quantity;
/**
* Returns the value of {@link #goods goods} to this object.
*
* @hibernate.many-to-one cascade="none"
* class="br.ufpe.scacin.model.Goods"
* column = "FK_GOODS_ID"
* not-null="true"
*
* @return Returns the goods.
*/
public Goods getGoods() {
return this.goods;
}
/**
* Sets the value of {@link #goods} to this object.
*
* @param goods The goods to set.
*/
public void setGoods(Goods goods) {
this.goods = goods;
}
/**
* Returns the value of {@link #quantity} to this object.
*
* @hibernate.property column="GOODS_QUANTITY"
* not-null="true"
* type="int"
* update="true"
*
* @return Returns the quantity.
*/
public int getQuantity() {
return this.quantity;
}
/**
* Sets the value of {@link #quantity} to this object.
*
* @param quantity The quantity to set.
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/**
*
* @param obj
* @return
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
boolean result = false;
if (obj instanceof RelationshipPurchaseGoods) {
result = EqualsBuilder.reflectionEquals(this, obj);
}
return result;
}
/**
* @return
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
/**
* @return
*
* @see java.lang.Object#toString()
*/
public String toString() {
ToStringStyle style = ToStringStyle.MULTI_LINE_STYLE;
return ToStringBuilder.reflectionToString(this, style);
}
}[/code]
Como o relacionamento é bidirecional, não precisei colocar um atributo Purchase nessa classe. Em Purchase, eu tenho o seguinte:
/**
* Returns the value of {@link #relationships} to this object.
*
* @hibernate.bag cascade="save-update"
* inverse="true"
* lazy="true"
* table="JOIN_PURCHASE_GOODS"
*
* @hibernate.collection-key column="FK_PURCHASE_ID"
*
* @hibernate.collection-composite-element
* class = "br.ufpe.scacin.model.RelationshipPurchaseGoods"
*
* @return Returns the relationships.
*/
public List getRelationships() {
return this.relationships;
}
O que vai gerar o seguinte arquivo para mapeamento:
[code]<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="br.ufpe.scacin.model.Purchase"
table="SCACIN_PURCHASE"
dynamic-update="false"
dynamic-insert="false"
>
<id
name="id"
column="PURCHASE_ID"
type="long"
unsaved-value="-1"
>
<generator class="native">
</generator>
</id>
<many-to-one
name="costumer"
class="br.ufpe.scacin.model.User"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="USER_ID"
not-null="true"
/>
<property
name="date"
type="calendar"
update="true"
insert="true"
access="property"
column="PURCHASE_DATE"
not-null="true"
/>
<property
name="origin"
type="string"
update="true"
insert="true"
access="property"
column="PURCHASE_ORIGIN"
not-null="true"
/>
<bag
name="relationships"
table="JOIN_PURCHASE_GOODS"
lazy="true"
inverse="false"
cascade="all"
>
<key
column="FK_PURCHASE_ID"
>
</key>
<composite-element
class="br.ufpe.scacin.model.RelationshipPurchaseGoods"
>
<many-to-one
name="goods"
class="br.ufpe.scacin.model.Goods"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="FK_GOODS_ID"
not-null="true"
/>
<property
name="quantity"
type="int"
update="true"
insert="true"
access="property"
column="JOIN_PURCHASE_GOODS_QUANTITY"
not-null="true"
/>
</composite-element>
</bag>
</class>
</hibernate-mapping>[/code]
O erro é o seguinte, o hibernate simplesmente não consegue relacionar Goods ao objeto de relacionamento e então quando tento salvar o Purchase tenho o seguinte log com o erro:
[quote]Hibernate: insert into JOIN_PURCHASE_GOODS (FK_PURCHASE_ID, FK_GOODS_ID, JOIN_PURCHASE_GOODS_QUANTITY) values (?, ?, ?)
04/08/2004 19:35:42 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1048, SQLState: S1000
04/08/2004 19:35:42 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
04/08/2004 19:35:42 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1048, SQLState: S1000
04/08/2004 19:35:42 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
04/08/2004 19:35:42 net.sf.hibernate.JDBCException <init>
SEVERE: Could not execute JDBC batch update
java.sql.BatchUpdateException: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1367)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:122)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2417)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2371)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:386)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:316)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:211)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:148)
at $Proxy2.insert(Unknown Source)
at br.ufpe.scacin.manager.PurchaseManager.insert(PurchaseManager.java:95)
at br.ufpe.scacin.SCACInFacade.insert(SCACInFacade.java:314)
at br.ufpe.scacin.SCACInFacade.main(SCACInFacade.java:506)
04/08/2004 19:35:42 net.sf.hibernate.impl.SessionImpl execute
SEVERE: Could not synchronize database state with session
net.sf.hibernate.JDBCException: Could not execute JDBC batch update
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:129)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2417)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2371)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:386)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:316)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:211)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:148)
at $Proxy2.insert(Unknown Source)
at br.ufpe.scacin.manager.PurchaseManager.insert(PurchaseManager.java:95)
at br.ufpe.scacin.SCACInFacade.insert(SCACInFacade.java:314)
at br.ufpe.scacin.SCACInFacade.main(SCACInFacade.java:506)
Caused by: java.sql.BatchUpdateException: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1367)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:122)
… 13 more
04/08/2004 19:35:42 org.springframework.jdbc.support.SQLStateSQLExceptionTranslator translate
INFO: Translating SQLException with SQLState ‘S1000’ and errorCode ‘1048’ and message [General error, message from server: “Column ‘FK_GOODS_ID’ cannot be null”]; SQL was [null] for task [HibernateTemplate]
org.springframework.jdbc.UncategorizedSQLException: (HibernateTemplate): encountered SQLException [General error, message from server: “Column ‘FK_GOODS_ID’ cannot be null”]; nested exception is java.sql.BatchUpdateException: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
java.sql.BatchUpdateException: General error, message from server: "Column ‘FK_GOODS_ID’ cannot be null"
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1367)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:122)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2417)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2371)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:386)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:316)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:211)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:148)
at $Proxy2.insert(Unknown Source)
at br.ufpe.scacin.manager.PurchaseManager.insert(PurchaseManager.java:95)
at br.ufpe.scacin.SCACInFacade.insert(SCACInFacade.java:314)
at br.ufpe.scacin.SCACInFacade.main(SCACInFacade.java:506)[/quote]
Mais detalhes:
Hibernate 2.1.4
MySQL 4.0
Windows 2000
A DDL da tabela de join:
create table JOIN_PURCHASE_GOODS (
FK_PURCHASE_ID BIGINT not null,
FK_GOODS_ID BIGINT not null,
GOODS_QUANTITY INTEGER not null
)type=InnoDB;
Qualquer sugestão é muito bem vinda.
valeuz…