-->
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.  [ 15 posts ] 
Author Message
 Post subject: insert but should be update...
PostPosted: Wed Nov 24, 2004 4:13 pm 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
Hibernate version: 2.1.6

Name and version of the database you are using: MySQL 4.1


Hi,

I have two subclasses Player and TeamManager which extends a class Person. Both subclasses are mapped as joined-subclasses.

A Player and a TeamManager can belong to one Team. Because of multiple players can join the same team, there is a convenience method addPlayers in class Team.

The mapping excerpts for class Player and TeamManager:

<joined-subclass
name="de.soccermanager.person.entity.Player"
table="PLAYER"
dynamic-update="false"
dynamic-insert="false"
>
<key
column="PLAYER_ID"
/>

<many-to-one
name="team"
class="de.soccermanager.team.entity.Team"
cascade="save-update"
outer-join="auto"
update="true"
insert="true"
access="property"
column="TEAM_ID"
unique="false"
/>
....
</joined-subclass>
<joined-subclass
name="de.soccermanager.person.entity.TeamManager"
table="TEAM_MANAGER"
dynamic-update="false"
dynamic-insert="false"
>
<key
column="TEAM_MANAGER_ID"
/>

<many-to-one
name="team"
class="de.soccermanager.team.entity.Team"
cascade="save-update"
outer-join="auto"
update="true"
insert="true"
access="property"
column="TEAM_ID"
unique="false"
/>
...
</joined-subclass>


Mapping excerpt of class Team:

<class
name="de.soccermanager.team.entity.Team"
table="TEAM"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
optimistic-lock="version"
>

<id
name="id"
column="TEAM_ID"
type="long"
unsaved-value="null"
>
<generator class="native">
</generator>
</id>

<one-to-one
name="teamManager"
class="de.soccermanager.person.entity.TeamManager"
cascade="none"
outer-join="auto"
constrained="false"
property-ref="team"
/>

<set
name="players"
lazy="true"
inverse="true"
cascade="none"
sort="unsorted"
>

<key
column="TEAM_ID"
>
</key>

<one-to-many
class="de.soccermanager.person.entity.Player"
/>

</set>
....
</class>

I wrote a testcase which inserts a teammanager, a team and a player. Here is the code:

public void testInsertTeamManager() throws InfrastructureException{
TeamManager teamManager = new TeamManager();
Team team = new Team();

PersonDAO personDAO = new PersonDAO();

team.setTeamName("Bayern");
teamManager.setName("Magath");

team.setTeamManager(teamManager);

teamManager.setTeam(team);

personDAO.insertOrUpdatePerson(teamManager);

HibernateUtil.commitTransaction();
HibernateUtil.closeSession();
}

public void testInsertPlayer() throws InfrastructureException{
PersonDAO personDAO = new PersonDAO();

Player player = new Player();

player.setName(Ballack);
...

team.addPlayer(player);


personDAO.insertOrUpdatePerson(player);

HibernateUtil.commitTransaction();
HibernateUtil.closeSession();
}

This is the method invoked:

public void insertOrUpdatePerson(Person person) throws InfrastructureException{
Session session = HibernateUtil.getSession();

try{
session.saveOrUpdate(person);

}catch(HibernateException ex){
throw new InfrastructureException(ex);
}
}
}

I am using the Session-Local-Thread pattern. After executing the code, I have the same team object persisted twice to the database. TeamManager references one Team (row) and Player the other Team (row).

Obviously I miss an important Hibernate concept: As far as I understand after executing testInsertTeamManager() I have inserted the TeamManager and the Team to the database. Because the session is closed, both objects are detached.

Then, in the method testInsertPlayer() I add a player to the team. This happens within the session, therefore object Team should be reassociated to this (new) session. Finally, because of the reassociation, I would expect that Hibernate updates Team but instead inserts Team again!

Here is the generated sql output from Hibernate:

Hibernate: insert into TEAM (TEAM_NAME) values (?)
Hibernate: insert into ADDRESS (CITY, COUNTRY, EMAIL, HOME_PHONE, MOBILE_PHONE, POSTAL_CODE, STREET, STREET_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PERSON (ADDRESS_ID, NATIONALITY, GENDER, ATTITUDE, HEALTHINESS, MORALITY, RELIABLENESS, SELFCONFIDENCE, DATEOFBIRTH, FIRSTNAME, LASTNAME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into TEAM_MANAGER (DATE_MEMBERSHIP_START, NUMBER_GAMES_DRAW, NUMBER_GAMES_LOST, NUMBER_GAMES_WON, TEAM_ID, TS_LAST_LOGIN, TEAM_MANAGER_ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into TEAM (TEAM_NAME) values (?)
Hibernate: insert into ADDRESS (CITY, COUNTRY, EMAIL, HOME_PHONE, MOBILE_PHONE, POSTAL_CODE, STREET, STREET_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PERSON (ADDRESS_ID, NATIONALITY, GENDER, ATTITUDE, HEALTHINESS, MORALITY, RELIABLENESS, SELFCONFIDENCE, DATEOFBIRTH, FIRSTNAME, LASTNAME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PLAYER (TEAM_ID, POSITION, CONTRACT_PERIOD, SALARY, PLAYER_ID) values (?, ?, ?, ?, ?)

I am stuck. Hopefully someone can help. Thanks.
Sven


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 25, 2004 10:41 am 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
Does no one have a clue?! Unfortunately I am not able to figure it out by myself. I am thankful for any hint.

Sven


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 26, 2004 1:37 am 
Newbie

Joined: Tue Nov 16, 2004 12:00 am
Posts: 1
Location: Calgary, AB
hibi,

I have a very similar issue right now, so I am waiting as (im)patiently as you are for some guru to answer this one!


Top
 Profile  
 
 Post subject: Re: insert but should be update...
PostPosted: Fri Nov 26, 2004 1:57 am 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
I didnt get all the way through your code, so I dont know for sure, but let me give you some hints.

1. Hibernate knows if it is inserting or updating based on the ID of the object. What is the type of the team_id? I dont know why I dont see that in your insert statement (does hibernate omit that from the log?)... or is the team name the id? that isnt what your mapping says, so Im confused
2. If you have an assigned ID (as opposed to native), then hibernate might not know if it is an insert or update, so call session.save(object); (insert) or session.update(object); (update). I highly recommend putting native keys on each object even if that is not your business primary key...
Regards,
Chris


Top
 Profile  
 
 Post subject: Re: insert but should be update...
PostPosted: Fri Nov 26, 2004 4:31 am 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
mchyzer wrote:
What is the type of the team_id?


Thanks for your reply. The TeamID is of (java) type Long:

<class
name="de.soccermanager.team.entity.Team"
table="TEAM"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
optimistic-lock="version"
>

<id
name="id"
column="TEAM_ID"
type="long"
unsaved-value="null"
>
<generator class="native">
</generator>
</id>

After executing insertTeamManager() where Team is automatically inserted too, the TeamId remains null. I am not sure if this is the expected behaviour or if Hibernate should assign the id - generated by mysql - directly after I call HibernateUtil.commitTransaction().

My guess is, because of the id null value, Hibernate insterts the Team value again instead of update it. Hm. Anymore ideas?

Sven


Top
 Profile  
 
 Post subject: Re: insert but should be update...
PostPosted: Fri Nov 26, 2004 3:06 pm 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
hibi99 wrote:
After executing insertTeamManager() where Team is automatically inserted too, the TeamId remains null. I am not sure if this is the


You are right, that is your problem. Your native id's are not working for some reason. You should see in the SQL where it tries to get that ID, and you arent seeing it. Then the object will have the id in it as well, which obviously isnt happening. So fix that problem and you are all set.

Good luck!

Chris


Top
 Profile  
 
 Post subject: Re: insert but should be update...
PostPosted: Tue Dec 07, 2004 7:27 am 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
mchyzer wrote:
Then the object will have the id in it as well, which obviously isnt happening. So fix that problem and you are all set.


But this is the exact problem! I do not know why Hibernate does not assign the (generated) id to the object. I thought it has something to do with MySQL and tried HSQLDB instead, but no effect. The problem remains.

I wrote a second testcase which does not use the Session-Local-Thread-Pattern:

import java.sql.Timestamp;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.Date;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;

import net.sf.hibernate.cfg.Configuration;

import de.persistencemanager.util.InfrastructureException;
import de.soccermanager.constant.Constant;
import de.soccermanager.constant.enumeratedtypes.Gender;
import de.soccermanager.person.entity.Address;
import de.soccermanager.person.entity.Player;
import de.soccermanager.person.entity.TeamManager;
import de.soccermanager.team.entity.Team;

import junit.framework.TestCase;

/**
* @author sven
*
* TODO Kurzbeschreibung der Klasse
*/
public class TestInsertDataWithoutHibernateUtil extends TestCase {
Player player = new Player();
TeamManager teamManager = new TeamManager();
Team team = new Team();
Address address = null;

Session session;
Transaction tx;
static Configuration configuration;
static SessionFactory sessionFactory;

static {
try {
configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();

} catch (Throwable ex) {

throw new ExceptionInInitializerError(ex);
}
}




/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();

team.setStrTeamName("HSV");

}

/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}

/**
* Constructor for TestInsertData.
* @param name
*/
public TestInsertDataWithoutHibernateUtil(String name) {
super(name);

}

public void testInsertTeamManager() throws InfrastructureException{
assertNotNull("teamManager == null", teamManager);

try {
session = sessionFactory.openSession();

tx = session.beginTransaction();
} catch (HibernateException e) {

e.printStackTrace();
}

teamManager.setStrFirstName("Thomas");
...


address = new Address();

address.setStrStreet("Schreyerstr.");
...

teamManager.setAddress(address);

team.setTeamManager(teamManager);

teamManager.setTeam(team);

try {

session.save(teamManager);
tx.commit();


} catch (HibernateException e1) {

e1.printStackTrace();
}
finally{
try {
session.close();
} catch (HibernateException e2) {

e2.printStackTrace();
}
}
}

public void testInsertPlayer() throws InfrastructureException{

try {
session = sessionFactory.openSession();

tx = session.beginTransaction();
} catch (HibernateException e) {

e.printStackTrace();
}

player = new Player();
address = new Address();

player.setStrFirstName("Diego";
...


address.setStrStreet("Hollywood Bvd");
...

player.setAddress(address);


assertNotNull("teamId == null", team.getId()); //fails!!!!!

team.addPlayer(player);

assertNotNull("team == null", player.getTeam());


try {
session.save(player);

tx.commit();
} catch (HibernateException e1) {

e1.printStackTrace();
}
finally{
try {
session.close();
} catch (HibernateException e2) {

e2.printStackTrace();
}
}
}
}


The highlighted line is an unexpected result. I would assume, after I have inserted TeamManager (Team is being inserted automatically then..) that Hibernate assigned the id to this object via reflection. But obviously this is not the case. The id remains null and therefore - I conclude - Hibernate will insert the Team object again instead of updating it. Why is it not assigned?!

This must be trivial, but I cannot find my mistake. Any help is appreciated.

Sven


Top
 Profile  
 
 Post subject: Re: insert but should be update...
PostPosted: Tue Dec 07, 2004 11:59 am 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
hibi99 wrote:
This must be trivial, but I cannot find my mistake. Any help is appreciated.



You are right, this *should be* trivial. We will get it working.

Is it assigning the number in the DB (look at the data)? The type of the column in MySQL must be auto-increment int. Dont know about hsqldb.

The mapping must have generator of native which it looks like you have.

<id name="id" column="ID" unsaved-value="0">
<generator class="native"/>
</id>

When saving the first time, the type of the column must be your unsaved value. If int, this is 0 by default. Maybe try changing the type to long instead of Long. I only use primitives and it works fine in MySQL. Also, set the log level to debug and look at the actual SQL going back and forth and make sure that SQL does what it is supposed to.

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 08, 2004 7:06 am 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
Chris,

I changed the id value to the primitive type long with no positive effect.

I did another test where I am fetching the TeamID from the database and assigned it to the TeamObject (setId(value)) before the second testMethod is executed. And voila I get the expected sql:

Hibernate: insert into TEAM (TEAM_NAME) values (?)
Hibernate: insert into ADDRESS (CITY, COUNTRY, EMAIL, HOME_PHONE, MOBILE_PHONE, POSTAL_CODE, STREET, STREET_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PERSON (ADDRESS_ID, NATIONALITY, GENDER, ATTITUDE, HEALTHINESS, MORALITY, RELIABLENESS, SELFCONFIDENCE, DATEOFBIRTH, FIRSTNAME, LASTNAME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into TEAM_MANAGER (DATE_MEMBERSHIP_START, NUMBER_GAMES_DRAW, NUMBER_GAMES_LOST, NUMBER_GAMES_WON, TEAM_ID, TS_LAST_LOGIN, TEAM_MANAGER_ID) values (?, ?, ?, ?, ?, ?, ?)
team ID = 3 //retrieved from the database and assigned to TeamObject
Hibernate: insert into ADDRESS (CITY, COUNTRY, EMAIL, HOME_PHONE, MOBILE_PHONE, POSTAL_CODE, STREET, STREET_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PERSON (ADDRESS_ID, NATIONALITY, GENDER, ATTITUDE, HEALTHINESS, MORALITY, RELIABLENESS, SELFCONFIDENCE, DATEOFBIRTH, FIRSTNAME, LASTNAME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PLAYER (TEAM_ID, POSITION, CONTRACT_PERIOD, SALARY, PLAYER_ID) values (?, ?, ?, ?, ?)
Hibernate: update TEAM set TEAM_NAME=? where TEAM_ID=?

So what could be the reasons that Hibernate did not assign the id to the TeamObject "automagically"??? Here again, the mapping excerpt:

/**
* @return Returns the id.
*
* @hibernate.id
* generator-class="native"
* type="long"
* unsaved-value="null"
* column="TEAM_ID"
*
*/
public Long getId() {
return id;
}

results in

<id
name="id"
column="TEAM_ID"
type="long"
unsaved-value="null"
>
<generator class="native">

</generator>
</id>


the generated ddl for mysql is

create table TEAM (
TEAM_ID bigint not null auto_increment,
TEAM_NAME char(32) not null,
TEAM_MANAGER_ID bigint,
primary key (TEAM_ID)
);


Thanks in advance.

Sven


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 08, 2004 11:37 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
If you don't have assigned ids this should work.
If you don't trust your db's id generation for some reason try the increment or uuid generator (check the docs if you consider using them for production).

If assigned ids is a must for you you have the following options:
  • specify an appropriate unsave-value in the id tag.
  • specify unsaved-value="null" for the version and make sure the JAVA property is an Integer and not an int
  • implement the Interceptor method isUnsaved for the Child class.


HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 11, 2004 5:32 pm 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
ernst_pluess wrote:
If you don't have assigned ids this should work.


I do not have assigned ids. I am using the native type, so MySQL is responsible for generating the ids. Every object has an id of type Long. So null indicates that this is an unsaved value. I still have no idea why the following does not work:

start session
create Team object
create TeamManager object
assign Team to TeamManager
save TeamManager (because of cascade="save-update" Team is also being persisted.)
commit
end session

Object Team is now detached. I would assume here, that Hibernate has assigned the id which has been generated by MySQL automatically to Team. But it did not! Why not?

Second operation:

start session
create Player object
add Player to Team and assign Team to Player (Team is now reassociated to session)
save Player (cascade="save-update" for Team object).
commit
end session

Here I would expect, that the object Team is being updated in the database, but instead it is inserted again. So I have two Team objects in the database, one references TeamManager and the other one Player!

Meanwhile I really get frustated on that thing. One solution would be to QueryByExample for Team object and assign this object to Player. But to do this manually is cumbersome and does not make sense to me when I already have the object anyway.

Any solutions?!

Sven


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 11, 2004 9:30 pm 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
His mapping shows that he doesnt have assigned ids... I would try to download a simple example of this somewhere (an object, a mapping, a table definition, and some java code) and see it work. Then make changes to it until it fits your case. Something is a little off...

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 12, 2004 3:19 pm 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
mchyzer wrote:
His mapping shows that he doesnt have assigned ids... I would try to download a simple example of this somewhere (an object, a mapping, a table definition, and some java code) and see it work. Then make changes to it until it fits your case. Something is a little off...

Chris


I guess I have no choice so I will setup a simple example and see if it works. If not, I drop Hibernate and go back to OJB.... Thanks Chris.

Sven


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 13, 2004 3:44 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
Did you specify the primariky as autoincrement? AFAIK that's wat Hibernate expects with native ids for MySql.

You can also tell Hibernate to generate your db schema. Use the generated one or at least compare it to yours.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 13, 2004 6:41 am 
Beginner
Beginner

Joined: Mon Nov 08, 2004 11:58 am
Posts: 20
Yes the pk is incremented automatically.

Yesterday I setup a little example to see if it works at all and it does. So I have probably some wrong declarations in my mappings. I am going to debug this now.

Sven


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 15 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.