• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Bidirection join broken in one direction?

 
Rob Fry
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm currently grappling with converting an app which used JDBC and handcoded SQL to Hibernate so it's more robust/scaleable (in theory, this has proven to be a nightmare!). Due to it being a conversion job which was itself an enhancement of a previous application, a legacy database is involved, and the database schema is actually broken.

The problem I have is this. And apologies for the wordiness for what is I suspect a very simple problem but I figure the more you know the easier to answer.

I have a Transmitter object, which is persistent.

I also have a TransmitterLocation object, which is persistent.

There exists a one to one relationship between them. (Seems a bit odd maybe to have the location as a separate object, but there is a potential option to have transmitters with multiple locations in the future, and they did have them in the past. For now, however, it is a one-to-one relationship, which is why I say the schema is broken - there is no such constraint at the SQL level. The joy of legacy databases... Although the Java front end is coded in such a way that this constraint should never be broken anyway.).

Note that not every Transmitter has a TransmitterLocation, though every TransmitterLocation must have a transmitter.


Here are some Hibernate annotations so you can see the mapping.

public class Transmitter {
@Id
@GeneratedValue
@Column(name = "TX_ID")
private int txId;

@OneToOne (optional = true)
@JoinColumn (name = "TX_ID", referencedColumnName = "TX_ID")
private TransmitterLocation loc;

.....
}

public class TransmitterLocation {

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

@OneToOne (optional = false)
@JoinColumn (name = "TX_ID")
private Transmitter tx;

....
}

The DB schema is pretty straightforward, TX_PLANPLACE was and may be again a join table...

Table TX
TX_ID (primary key) blah blah blah

Table TX_PLANPLACE
TX_PLANPLACE_ID (primary key) TX_ID (foreign key) blah blah blah


In the initialisation code I have...

locs = s.createQuery("from TransmitterLocation").list();
transmitters = s.createQuery("from Transmitter").list();

The problem is that the join, while supposedly bidirectional, is not. After running that initialisation code, from a given TransmitterLocation I can get to a Transmitter. However, from a Transmitter, if I call getTransmitterLocation, it returns null - even if a TransmitterLocation exists.

So only one direction of the relationship is being modelled - something is wrong with the annotation in the Transmitter class. Oddly enough when saving the TransmitterLocation objects everything seems fine, it doesn't throw any exceptions and the database matches what was in memory. It is when recalling persisted objects that things come apart.

Any help on this out there?
 
Angel Taveras
Ranch Hand
Posts: 84
Eclipse IDE Hibernate Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Rob, i think the problem it's the mapping itself, not that the Bidirection join it's broken.

When dealing with bidirectional mapping you should only map one of the sides with the attribute mappedBy, this will make the mapping a lot easier because it will configure accordingly to the inverse mapping avoiding any distinct configuration on any one of the sides.

Also there in the mapping you have an error in the referenceColumnName attribute. This value must be the name of the property on the inverse entity not the column name of the inverse entity, meaning that the correct value must be id not TX_ID.

This suggest the following mapping:



regards,
 
Rob Fry
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Angel Taveras:
When dealing with bidirectional mapping you should only map one of the sides with the attribute mappedBy, this will make the mapping a lot easier because it will configure accordingly to the inverse mapping avoiding any distinct configuration on any one of the sides.

Also there in the mapping you have an error in the referenceColumnName attribute. This value must be the name of the property on the inverse entity not the column name of the inverse entity, meaning that the correct value must be id not TX_ID.


Genius, this is it, it works now. I didn't realise mappedBy and referenceColumnName wanted Java attributes not SQL columns! Suddenly everything is much clearer, thanks.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic