-->
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.  [ 6 posts ] 
Author Message
 Post subject: Bidirectional @OneToOne with shared assigned primary keys
PostPosted: Tue Aug 14, 2007 2:44 pm 
Beginner
Beginner

Joined: Sat Sep 24, 2005 11:04 pm
Posts: 21
Hibernate Core version: 3.2.5.GA

Hibernate Annotations version: 3.3.0.GA

Problem Description:

As you might have guessed from the title, I'm having some issues with persisting an annotated bidirectional one-to-one association using shared primary keys. Both the parent and child extend an abstract domain object that generates a unique Id upon construction. The problem seems to be with the proper substitution of the id on the child entity with that of the parent in the relationship. Instead of the parent's id being used when cascading the insert of the child, the application generated id of the child is used which violates a foreign key constraint when the session is flushed. It seems to work if I explicitly override the id of the child with that of the parent ( child.setId(parent.getId()) ) but I was under the impression that this would be handled automatically, assuming the classes are annotated correctly.

Abstract Parent Class:

Code:
@MappedSuperclass
public abstract class AbstractDomainObject implements Serializable {

   protected String id;
   protected Integer version;

   public AbstractDomainObject() {
      setId(UUIDGenerator.getInstance().generateRandomBasedUUID().toString());
   }
        ...
}


Parent Entity:

Code:
@Entity
public class Stock extends AbstractDomainObject {

   private String symbol;
   private Company company;

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   public Company getCompany() {
      return company;
   }
        ...
}


Child Entity:

Code:
@Entity
public class Company extends AbstractDomainObject {

   private String name;
   private String url;
   private Stock stock;
      
   @OneToOne(mappedBy = "company")
   public Stock getStock() {
      return stock;
   }
        ...
}


I've also tried overriding the getId() method on the child class (Company) and using:

@GeneratedValue(generator = "foreign")
@GenericGenerator(name = "foreign", strategy = "foreign", parameters = {@Parameter(name = "property", value = "stock")})

but to no avail. Anyone know what's up with this? I've looked at a couple of other posts (one which reported this as a possible bug in an old version of hibernate annotations but has since been marked as fixed), but can't seem find exactly what I'm looking for.

Thanks for the help ...

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

Code:
Stock stock = new Stock();
stock.setSymbol("symbol");
stock.setCompany(new Company());
      
stock.getCompany().setName("companyName");
stock.getCompany().setUrl("companyUrl");
stock.getCompany().setStock(stock);          
           
stockDao.save(stock);


Full stack trace of any exception that occurs:

2007-08-14 13:09:03,479 ERROR hibernate.util.JDBCExceptionReporter::logExceptions(78) - Cannot add or update a child row: a foreign key constraint fails (`company`, CONSTRAINT `FK_company_1` FOREIGN KEY (`id`) REFERENCES `stock` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

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

The generated SQL (show_sql=true):

2007-08-14 13:09:03,432 DEBUG org.hibernate.SQL::log(401) - insert into Stock (version, symbol, id) values (?, ?, ?)
2007-08-14 13:09:03,463 DEBUG hibernate.type.IntegerType::nullSafeSet(133) - binding '0' to parameter: 1
2007-08-14 13:09:03,463 DEBUG hibernate.type.StringType::nullSafeSet(133) - binding 'symbol' to parameter: 2
2007-08-14 13:09:03,463 DEBUG hibernate.type.StringType::nullSafeSet(133) - binding 'bda4ffb2-9b07-4d11-806b-03cee222d85e' to parameter: 3
2007-08-14 13:09:03,463 DEBUG org.hibernate.SQL::log(401) - insert into Company (version, name, url, id) values (?, ?, ?, ?)
2007-08-14 13:09:03,463 DEBUG hibernate.type.IntegerType::nullSafeSet(133) - binding '0' to parameter: 1
2007-08-14 13:09:03,463 DEBUG hibernate.type.StringType::nullSafeSet(133) - binding 'companyName' to parameter: 2
2007-08-14 13:09:03,463 DEBUG hibernate.type.StringType::nullSafeSet(133) - binding 'companyUrl' to parameter: 3
2007-08-14 13:09:03,463 DEBUG hibernate.type.StringType::nullSafeSet(133) - binding '9ac37200-ac93-4cb2-b953-5c928c25d07c' to parameter: 4


Last edited by burroinquieto on Wed Aug 15, 2007 10:52 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 15, 2007 7:36 am 
Newbie

Joined: Wed Aug 15, 2007 7:32 am
Posts: 2
I am having what I think is the same problem:
My POJOS:

++++++++ PlayerDetailsDTO +++++++
@Entity
@Table(name="PLAYER_DETAILS")
public class PlayerDetailsDTO implements Serializable{
public static final long serialVersionUID = 1L;

@Id
@Column(name="PLAYER_ID")
private int id;

@Column(name="TITLE")
private String title;

.....

@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn(name="PLAYER_ID")
private PlayerDTO player;

+++++++ PlayerDTO.java ++++++++++
@Entity
@Table(name="PLAYER")
public class PlayerDTO implements Serializable {
public static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="PLAYER_ID")
private int id;

....

@OneToOne(mappedBy="player", cascade=CascadeType.ALL)
private PlayerDetailsDTO playerDetails;

.....

PlayerDetailsDTO primary key is PlayerDTO's primary key.

This is what I do on the code to create a player:
---------------------------
PlayerDTO player = new PlayerDTO();

//set players attributes
....

//player details to store the email
PlayerDetailsDTO playerDetails = new PlayerDetailsDTO();
playerDetails.setId(player.getId());
playerDetails.setEmail(email);
player.setPlayerDetails(playerDetails);

player = new PlayerDAO(emf).create(player);
--------------------------------


The result is that a player record is created and then a playerDetails record is created but NOT with the id of the player record just inserted. I don't have a constraint so I don't get an error. It inserts a player with id=0.

Hibernate should put the id of the player inserted in the playerDetails before inserting it, but it is not doing this.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 15, 2007 9:01 am 
Newbie

Joined: Wed Aug 15, 2007 7:32 am
Posts: 2
[quote="proza"]I am having what I think is the same problem:
My POJOS:

++++++++ PlayerDetailsDTO +++++++
@Entity
@Table(name="PLAYER_DETAILS")
public class PlayerDetailsDTO implements Serializable{
public static final long serialVersionUID = 1L;

@Id
@Column(name="PLAYER_ID")
private int id;

@Column(name="TITLE")
private String title;

.....

@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn(name="PLAYER_ID")
private PlayerDTO player;

+++++++ PlayerDTO.java ++++++++++
@Entity
@Table(name="PLAYER")
public class PlayerDTO implements Serializable {
public static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="PLAYER_ID")
private int id;

....

@OneToOne(mappedBy="player", cascade=CascadeType.ALL)
private PlayerDetailsDTO playerDetails;

.....

PlayerDetailsDTO primary key is PlayerDTO's primary key.

This is what I do on the code to create a player:
---------------------------
PlayerDTO player = new PlayerDTO();

//set players attributes
....

//player details to store the email
PlayerDetailsDTO playerDetails = new PlayerDetailsDTO();
playerDetails.setId(player.getId());
playerDetails.setEmail(email);
player.setPlayerDetails(playerDetails);

player = new PlayerDAO(emf).create(player);
--------------------------------


The result is that a player record is created and then a playerDetails record is created but NOT with the id of the player record just inserted. I don't have a constraint so I don't get an error. It inserts a player with id=0.

Hibernate should put the id of the player inserted in the playerDetails before inserting it, but it is not doing this.[/quote]

It worked before when I was using mapping files.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 23, 2007 11:16 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
The basic idea is to put the id definition down to the parent and child class (not the superclass), this will allow you to define the foreign generator

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 23, 2009 5:05 am 
Beginner
Beginner

Joined: Sat Sep 24, 2005 11:04 pm
Posts: 21
Does anyone know if there's an open JIRA ticket for this? I'm currently using hibernate annotations 3.4.0.GA and it doesn't look like this is supported yet. It's kind of a drag not being able to leverage inheritance for my id / version properties along with id generation behavior in a superclass.

I've tried overriding the get method of the identifier using a generation strategy of foreign along with the @AttributeOverride annotation (thinking the presence of this annotation might act as a cue for hibernate to allow the overrided id behavior) but to no avail.

Also tried configuring the one-to-one using many-to-one semantics (non-shared primary key) but once again, was left scratching my head on this one.

Anyone?


Top
 Profile  
 
 Post subject: Re: Bidirectional @OneToOne with shared assigned primary keys
PostPosted: Fri Oct 09, 2009 9:41 am 
Newbie

Joined: Fri Oct 02, 2009 11:37 am
Posts: 1
Hi Emmanuel,

We would be most grateful if someone from the hibernate team could provide a detailed and clear description about the solution so this issue. One-to-one relationships in a database with shared primary keys are now something quite common is datatase designs especially because designers use quite often vertical partitioning of database tables to better optimize the schema.

Is this a bug in hibernate? If so, is there a quick workaround (not risky stuff though) for this bug?
Or is there some different steps (setting different attributes for annotations) that we may not have quite well understood that has to be done to have it working (I assume this may perhaps be possible due to the fact that it is something that works with the xml configuration)?

Thanks ver much for your help


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