persistence@glassfish.java.net

Re: Recursive relationship

From: Michael Bouschen <Michael.Bouschen_at_Sun.COM>
Date: Thu, 12 Jan 2006 15:30:02 +0100

Hi Pavel,

there have been changes in this part of the spec. But as I understand
section "9.1.6 JoinColumn Annotation", the default it is still the
relationship field name + '_' + primary key column. I agree, assuming
the name of the foreign key column is PARENT_ID, the default should
apply and the field should be mapped automatically.

Markus,
I read the spec that your default "class name + '_' + primary key
column" applies in case of a join table. Am I right?

Regards Michael

> Has this changed in the spec? What I read in my older copy should apply
> in Martin's case and should work automatically:
>
> @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
> public @interface JoinColumn {
> String name() default "";
> String referencedColumnName() default "";
> boolean unique() default false;
> boolean nullable() default true;
> boolean insertable() default true;
> boolean updatable() default true;
> String columnDefinition() default "";
> String secondaryTable() default "";
> }
>
> Type: String
> Name: name
> Description: (Optional) The name of the foreign key column.
> The table in which it is found depends upon the context.
> If the join is for a OneToOne or ManyToOne mapping or for
> a secondary table joined to a primary table, then the
> foreign key column is in the table of the source entity.
> If the join is for a ManyToMany then the foreign key is
> in a join table.
>
> Default: (Only applies if single join column being used.)
> The concatenation of following: the name of the referencing
> relationship property or field of the referencing entity;
> "_"; the name of referenced primary key column.
>
> Pls correct me if I am wrong.
> -pavel
>
> Markus Fuchs wrote:
>
>> Sahoo,
>>
>> Oracles (our) behavior is spec conform. If Martin wants automatic
>> mapping, he must name the relationship "category" and the fk column
>> CARTEGORY_ID.
>>
>> I doubt the this is a bug. It's rather a feature request. Hibernate's
>> behavior is not portable.
>>
>> What do you think?
>>
>> Thanks,
>>
>> -- markus.
>>
>> Sanjeeb Kumar Sahoo wrote:
>>
>>> Martin Adamek wrote:
>>>
>>>> Thanks Michael,
>>>>
>>>> that helped, it's working now. I just don't understand why it is
>>>> needed.
>>>
>>>
>>>
>>>
>>>
>>> looks like a bug to me. Pl file a bug in issue tracker.
>>>
>>> Thanks,
>>> Sahoo
>>>
>>>> My understanding was that there should be default applied, isn't it
>>>> clear from the context, which column I want to use? (and it's
>>>> working in Hibernate :-)
>>>>
>>>> Anyway, thanks for help.
>>>> -M
>>>>
>>>> Michael Bouschen wrote:
>>>>
>>>>> Hi Martin,
>>>>>
>>>>> I think the getParent method misses a JoinColumn annotation
>>>>> specifying the foreign key column for the parent-child
>>>>> relationship. I assume the table for the Category entity has a
>>>>> foreign key column e.g. PARENT_ID referring the Id column of the
>>>>> table. Then the annotation could look like:
>>>>> @ManyToOne()
>>>>> @JoinColumn(name="PARENT_ID")
>>>>> public Category getParent() {
>>>>> return parent;
>>>>> }
>>>>>
>>>>> Hope that helps.
>>>>>
>>>>> Regards Michael
>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> I tried to create entity which can be recursively pointing to
>>>>>> instances of same type. I want to use it for representing product
>>>>>> categories navigation menu:
>>>>>>
>>>>>> - Computers
>>>>>> - Laptops
>>>>>> - Cables
>>>>>> - ...
>>>>>> - Cameras
>>>>>> - Digital
>>>>>> - Cards
>>>>>> - MMC
>>>>>> - SD
>>>>>> - XD
>>>>>> - ...
>>>>>>
>>>>>> Following entity I can use in Hibernate EM in J2SE without
>>>>>> problems but on GlassFish I am experiencing problems on deployment
>>>>>> (see below).
>>>>>>
>>>>>> Entity:
>>>>>> ---%<---
>>>>>> package foo.entity;
>>>>>> import java.util.ArrayList;
>>>>>> import java.util.List;
>>>>>> import javax.persistence.*;
>>>>>>
>>>>>> @Entity
>>>>>> public class Category {
>>>>>> private Long id;
>>>>>> private String name;
>>>>>> private Category parent;
>>>>>> private List<Category> children;
>>>>>>
>>>>>> public Category() {
>>>>>> children = new ArrayList();
>>>>>> }
>>>>>>
>>>>>> @Id(generate = GeneratorType.AUTO)
>>>>>> public Long getId() {
>>>>>> return id;
>>>>>> }
>>>>>>
>>>>>> public void setId(Long id) {
>>>>>> this.id = id;
>>>>>> }
>>>>>>
>>>>>> public String getName() {
>>>>>> return name;
>>>>>> }
>>>>>>
>>>>>> public void setName(String name) {
>>>>>> this.name = name;
>>>>>> }
>>>>>>
>>>>>> @ManyToOne()
>>>>>> public Category getParent() {
>>>>>> return parent;
>>>>>> }
>>>>>>
>>>>>> public void setParent(Category parent) {
>>>>>> this.parent = parent;
>>>>>> }
>>>>>>
>>>>>> @OneToMany(mappedBy="parent", cascade={CascadeType.ALL})
>>>>>> public List<Category> getChildren() {
>>>>>> return children;
>>>>>> }
>>>>>>
>>>>>> public void setChildren(List<Category> children) {
>>>>>> this.children = children;
>>>>>> }
>>>>>> }
>>>>>> ---%<---
>>>>>>
>>>>>> GlassFish exceptions:
>>>>>> ---%<---
>>>>>> Exception [TOPLINK-48] (Oracle TopLink Essentials - 10g release 4
>>>>>> (10.1.4.0.0) (Build 051215Dev)):
>>>>>> oracle.toplink.essentials.exceptions.DescriptorException
>>>>>> Exception Description: Multiple writable mappings exist for the
>>>>>> field [CATEGORY.ID]. Only one may be defined as writable, all
>>>>>> others must be specified read-only.
>>>>>> Mapping: oracle.toplink.essentials.mappings.OneToOneMapping[parent]
>>>>>> Descriptor: RelationalDescriptor(foo.entity.Category -->
>>>>>> [DatabaseTable(CATEGORY)])
>>>>>> ---%<---
>>>>>>
>>>>>> Any idea, what's the problem?
>>>>>>
>>>>>> -M
>>>>>
>>>>>
>>>>>
>>>>>