Hibernate: many-to-many e atributos na tabela de associação

1 resposta
jack_ganzha
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:
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);
    }
}
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:
<?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>
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:
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 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)
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...

1 Resposta

jack_ganzha

Pois é, recado para mim mesmo: vai aprender a escrever casos de teste direito, seu burro! :smiley:

valeuz…

Criado 6 de agosto de 2004
Ultima resposta 9 de ago. de 2004
Respostas 1
Participantes 1