persistence@glassfish.java.net

Re: Recursive relationship

From: Pavel Buzek <Pavel.Buzek_at_Sun.COM>
Date: Thu, 12 Jan 2006 09:06:11 -0500

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
>>>>
>>>>
>>>>