-->
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.  [ 5 posts ] 
Author Message
 Post subject: OneToOne mapping with foreign keys, How to?
PostPosted: Fri Nov 21, 2008 9:38 am 
Newbie

Joined: Fri Nov 21, 2008 4:31 am
Posts: 3
Hello,

hopefully someone can help me with this sligtly exotic setup. I have two tables here which are associated OneToOne and I want them to be mapped onto a unidirectional association. When using the hibernate schema export it forces me to have the foreign key in the table which belongs to the java Object which holds the association. Is there any way to do it the other way round?

Ok here is the example:


That's how the database should look like:

Code:

+-----------------------------------+
| Config
+-----------------------------------+
| Id | name | ...
+-----------------------------------+

+-----------------------------------+
| ConfigElement
+-----------------------------------+
| Id | content | configId (unique, references config.id)
+-----------------------------------+



and the corresponding java code:

Code:
--------------------------------------------------------
@Entity
@Table(name = "Config")
@SequenceGenerator(
    name = "Config_SEQ_ID",
    sequenceName = "config_seq", allocationSize = 1)

public class Config {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Config_SEQ_ID")
    long id = -1;
    @OneToOne
    @JoinColumn(name = "configId")
    ConfigElement configElement;
    @Column
    String name;
...


Code:
@Entity
@Table(name = "ConfigElement")
@SequenceGenerator(
    name = "ConfigElement_SEQ_ID",
    sequenceName = "configElement_seq", allocationSize = 1)

public class ConfigElement {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ConfigElement_SEQ_ID")

    long id = -1;
    @Column
    String content;
   



Here is what hibernate generates:

Code:

    create table Config (
        id int8 not null,
        name varchar(255),
        configId int8,
        primary key (id)
    )

    create table ConfigElement (
        id int8 not null,
        content varchar(255),
        primary key (id)
    )

    alter table Config
        add constraint FK78A46F62A2070494
        foreign key (configId)
        references ConfigElement

    create sequence configElement_seq

    create sequence config_seq


I have to admit that this does not look like a too good dabase design, but I was wondering how things work if I have a Class hierarchy for ConfigElement with a OneTablePerClass strategy. In that case not foreign key is generated at all.

Well anyways: Does anyone know if the above is possible at all?

Thanks in advance for any hint.
Greetings
PeeR


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 3:57 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
According to the docs (http://www.hibernate.org/hib_docs/annot ... ml#d0e1039) it should be possible:

Quote:
The join column is declared with the @JoinColumn annotation which looks like the @Column annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join.


Maybe this does the trick:
Code:
@JoinColumn(referencedColumnName = "configId")


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2008 4:23 am 
Newbie

Joined: Fri Nov 21, 2008 4:31 am
Posts: 3
Hi,

thanks for your reply, but unfortunatly it does not work like this. As far as i understand the referencedColumn is typically used to indicate that any ohter than the target entity's primary key column is used.
Just in case you are interested in it, tried your example and it reported:

Code:
org.hibernate.MappingException: Unable to find column with logical name: configId in org.hibernate.mapping.Table(ConfigElement) and its related supertables and secondary tables
   at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:396)
   at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:102)
   at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:88)


If I choose to use the content column as the referenced column the following table is generated:

Code:
    @JoinColumn(referencedColumnName = "content")


results in:

Code:
    create table Config (
        id int8 not null,
        name varchar(255),
        configElement_content varchar(255),
        primary key (id)
    )


And to make that complete I could give that column configElement_content another name by using the name parameter:

Code:
    @JoinColumn(referencedColumnName = "content", name ="myForeignKeyColumn")


results in:
Code:

  create table Config (
        id int8 not null,
        name varchar(255),
        myForeignKeyColumn varchar(255),
        primary key (id)
    )


Greetings
PeeR


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2008 4:45 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
This doesn't make much sense to me. I interpret "column in the targeted entity" in the documentation as a column in the ConfigElement table.

But... I am not very familiar with annotations. We are using regular hbm.xml mapping files and we have a case just like this that works without any problem. So I think Hibernate is certainly able to handle this. Here is what we have:

In A.hbm.xml
Code:
<one-to-one
    name="b"
    class="B"
    constrained="false"
    property-ref="a"
/>


In B.hbm.xml
Code:
<many-to-one
    name="a"
    class="A"
    column="`a_id`"
    not-null="false"
    unique="true"
/>


Maybe there is no annotation equivalent to the property-ref attribute of the <one-to-one> tag?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2008 4:56 am 
Newbie

Joined: Fri Nov 21, 2008 4:31 am
Posts: 3
Hi,

too bad that I'm not used to xml-configuration ;-). Anyways what I noticed in your example is that in B.hbm.xml you have a many-to-one association. If I do that with the annotations it works perfecty:

Code:
    @OneToMany
    @JoinColumn(name ="configId")
    List<ConfigElement> configElements;


resutls in

Code:
-- no fk-column here
create table Config (
        id int8 not null,
        name varchar(255),
        primary key (id)
    )
-- but here:
    create table ConfigElement (
        id int8 not null,
        content varchar(255),
        configId int8,
        primary key (id)
    )
-- and the fk is included for free
alter table ConfigElement
        add constraint FKAD9F953A1A795262
        foreign key (configId)
        references Config


Thanks again for your input!

Greetings
PeeR


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