-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Automatic dirty checking and many-to-many associations
PostPosted: Tue Aug 16, 2005 7:14 pm 
Newbie

Joined: Sat Jul 23, 2005 7:19 pm
Posts: 11
I am trying to work with many-to-many association, and I try to adapt Item, Category and CategorizedItem that you can find in CaveatEmptor to my tables.

I have two tables: INTERNADOS and FAMILIARES, with a many-to-many association. That association (table INTERNADOS_FAMILIARES) has an attribute: acargo, that is a boolean.
Familiares is a java.util.Set<InternadoFamiliar> field in Internado. I added a method in Internado:

addFamiliar(Familiar f, boolean acargo)

that creates a new InternadoFamiliar that associates Internado instance with Familiar parameter and set relationship attribute.

Well, what I do is creating a Familiar, then I create an Internado, and I try to add an "InternadoFamiliar" instance with my method.
I suppose that "automatic dirty checking" would let me just to save Internado and Familiar, and that it would detect InternadoFamiliar and save it too. But when I to save I get a TransientObjectException that tells me that I had to save before, but because it tries to update an INTERNADO_FAMILIAR that doesn't exist.

I solved this by creating InternadoFamiliar after saving Internado and Familiar, but why automatic dirty checking doesn't detect this?

If you know of a tutorial for many-to-many associations with attributes in the relationship, please tell me, because I found it quite difficult.

Also, I looked for "foreign-key" parameter in <key> tag in the XML but I couldn't find anything, how do you use it?
foreign-key is in CaveatEmptor like-this:

<set name="categorizedItems" cascade="all-delete-orphan" inverse="true" lazy="true" access="field">
-
<key foreign-key="FK2_CATEGORIZED_ITEM_ID">
<column name="ITEM_ID" not-null="true" length="16"/>
</key>
<one-to-many class="CategorizedItem"/>
</set>

Hibernate version:
3.0.5
Mapping documents:


My tables have a lot of attributes, I cut them to get shorter my post (well, at least I tried to :) ), so may be the syntax is incorrect. Just know that Internado and Familiar have their Key (a String noAfiliado for Internado, and an Integer idFamiliar for Familiar) and an attribute apellidos (surname in English).
INTERNADO


public class Internado extends {

private Set<InternadoFamiliar> familiares = new HashSet<InternadoFamiliar>();

public String getNoAfiliado() {
return noAfiliado;
}

public void setNoAfiliado(String noAfiliado) {
this.noAfiliado = noAfiliado;
}

public String getApellidos() {
return apellidos;
}

public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}

public Internado() {
}

private String noAfiliado;

private String apellidos;

public Set<InternadoFamiliar> getFamiliares() {
return familiares;
}

public void addFamiliar(Familiar fam, boolean aCargo) {

InternadoFamiliar intFam = new InternadoFamiliar();
intFam.setAcargo(aCargo);
intFam.setFamiliar(fam);
intFam.setInternado(this);

this.getFamiliares().add(intFam);
}
}
INTERNADO.HBM.XML

?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.neaprog.geriatrico.datos.Internado"
table="INTERNADOS">
<id name="noAfiliado" column="NoAfiliado">
</id>
<property name="apellidos" type="string" column="apellidos" not-null="true"/>
<set name="familiares" access="field">
<key >
<column name="noAfiliado" not-null="true"/>
</key>
<one-to-many class="com.neaprog.geriatrico.datos.InternadoFamiliar"/>
</set>
</class>
</hibernate-mapping>
--------------------------------------
FAMILIAR
public class Familiar {

public Familiar() {
}
public int getIdFamiliar() {
return idFamiliar;
}

public void setIdFamiliar(int idFamiliar) {
this.idFamiliar = idFamiliar;
}

public String getApellidos() {
return apellidos;
}

public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
}
FAMILIARES.HBM.XML
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.neaprog.geriatrico.datos.Familiar"
table="FAMILIARES">
<id name="idFamiliar" column="idFamiliar">
<generator class="increment"/>
</id>
<property name="apellidos" type="string" column="apellidos"/>
</class>
</hibernate-mapping>

------------------------------------
INTERNADOFAMILIAR
public class InternadoFamiliar {

public InternadoFamiliar() {
}

private Id id = new Id();

private Internado internado;

private Familiar familiar;

private boolean acargo;

public Id getId() {
return id;
}

public Internado getInternado() {
return internado;
}

public void setInternado(Internado internado) {
this.internado = internado;
this.getId().noAfiliado = internado.getNoAfiliado();
}

public Familiar getFamiliar() {
return familiar;
}

public void setFamiliar(Familiar familiar) {
this.familiar = familiar;
this.getId().idFamiliar = familiar.getIdFamiliar();
}

public boolean isAcargo() {
return acargo;
}

public void setAcargo(boolean acargo) {
this.acargo = acargo;
}

public static class Id implements Serializable {

private String noAfiliado;

private Integer idFamiliar;

public Id() {}

public Id(String noAfiliado, Integer idFamiliar) {
this.noAfiliado = noAfiliado;
this.idFamiliar = idFamiliar;
}

public boolean equals(Object o) {
if (o instanceof Id) {
Id that = (Id)o;
return this.noAfiliado.equals(that.noAfiliado) &&
this.idFamiliar.equals(that.idFamiliar);
} else {
return false;
}
}

public int hashCode() {
return idFamiliar.hashCode() + noAfiliado.hashCode();
}

}

}
INTERNADOFAMILIAR.HBM.XML
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.neaprog.geriatrico.datos.InternadoFamiliar"
table="INTERNADOS_FAMILIARES">
<composite-id name="id" class="com.neaprog.geriatrico.datos.InternadoFamiliar$Id" access="field" unsaved-value="any">
<key-property name="idFamiliar" access="field" column="idfamiliar"/>
<key-property name="noAfiliado" access="field" column="noAfiliado"/>
</composite-id>
<property name="acargo" column="acargo" type="boolean" not-null="true" access="field"/>

<many-to-one name="internado" insert="false" update="false" not-null="true" access="field" column="noAfiliado"/>
<many-to-one name="familiar" insert="false" update="false" not-null="true" access="field" column="ITEM_ID"/>

</class>
</hibernate-mapping>

Code between sessionFactory.openSession() and session.close():

Transaction tx = sesionHb.beginTransaction();

Internado nuevoAbuelo = getInternadoDeVentana(); //put values into nuevoAbuelo

Familiar famACargo = jPanelFamiliar.getFamiliarDeVentana(); //put values into famACargo

nuevoAbuelo.addFamiliar(famACargo, true);
Set<InternadoFamiliar> familiares = nuevoAbuelo.getFamiliares();

sesionHb.save(famACargo);
sesionHb.save(nuevoAbuelo);

tx.commit();

Full stack trace of any exception that occurs:

74860 [AWT-EventQueue-0] ERROR def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:
com.neaprog.geriatrico.datos.InternadoFamiliar
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:216)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:99)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:63)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:652)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:914)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:23)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.guardarInternado(JIntFrameIngreso.java:230)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.ingresarInternado(JIntFrameIngreso.java:130)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.jButtonGuardarActionPerformed(JIntFrameIngreso.java:1097)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.access$700(JIntFrameIngreso.java:37)
at com.neaprog.geriatrico.ui.JIntFrameIngreso$8.actionPerformed(JIntFrameIngreso.java:990)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
at java.awt.Component.processMouseEvent(Component.java:5488)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3093)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1774)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

Name and version of the database you are using:
SQLServer 2000. JDBC: jTDS 1.1

The generated SQL (show_sql=true):

Hibernate: insert into FAMILIARES (apellidos, idFamiliar) values (?, ?)

Hibernate: insert into INTERNADOS (apellidos, NoAfiliado) values (?, ?)

Hibernate: update INTERNADOS set apellidos=? where NoAfiliado=?

Hibernate: update INTERNADOS_FAMILIARES set noAfiliado=? where idfamiliar=? and noAfiliado=?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 16, 2005 7:21 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
cascade="save-update"


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 16, 2005 8:45 pm 
Newbie

Joined: Sat Jul 23, 2005 7:19 pm
Posts: 11
Well, thank you. Now it tries to INSERT in the right order:

Hibernate: insert into FAMILIARES (apellidos, idFamiliar) values (?, ?)

Hibernate: insert into INTERNADOS (apellidos, NoAfiliado) values (?, ?)

Hibernate: insert into INTERNADOS_FAMILIARES (acargo, idfamiliar, noAfiliado) values (?, ?, ?)

but I still have an exception message:

50609 [AWT-EventQueue-0] ERROR util.JDBCExceptionReporter - INSERT instruction in conflict with COLUMN FOREIGN KEY 'FK_INTERNADOS_FAMILIARES_FAMILIARES' restriction. Conflict has appeared in database 'geriatrico', 'FAMILIARES' table, column 'idfamiliar'.
50609 [AWT-EventQueue-0] ERROR def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.ErrorCodeConverter.handledNonSpecificException(ErrorCodeConverter.java:92)
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:80)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:181)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:136)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.guardarInternado(JIntFrameIngreso.java:238)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.ingresarInternado(JIntFrameIngreso.java:139)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.jButtonGuardarActionPerformed(JIntFrameIngreso.java:1176)
at com.neaprog.geriatrico.ui.JIntFrameIngreso.access$800(JIntFrameIngreso.java:40)
at com.neaprog.geriatrico.ui.JIntFrameIngreso$10.actionPerformed(JIntFrameIngreso.java:1064)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
at java.awt.Component.processMouseEvent(Component.java:5488)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3093)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1774)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

SQLServer message is translated by me, because I have spanish version. But what it's saying is that it's trying to insert a new InternadoFamiliar but idFamiliar is not in Familiar.
I assume that I don't have to put in Familiar.hbm.xml a reference to the association (by now I don't need it).


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.