Eclipse Community Forums - RDF feed
https://www.eclipse.org/forums/
Eclipse Community Forums[Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423287/#msg_423287
I followed the ejb3_example on the many to many annotations. Ended up
with this
Exception in thread "main"
org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
Found Attribute Name but expected one of : Array End (}), = character,
Comma (,).
@ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
targetEntity="UserRole" mappedBy="role")
Current lexeme: PERSIST
at
org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
at
org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
at
org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
It is very explicit, but I cannot see what is different in structure to
the example.
Thx.
David]]>David Wynter2008-09-26T10:34:49-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423288/#msg_423288
I think there should be a comma between MERGE and PERSIST in the cascade attribute.
gr. Martin
David Wynter wrote:
> Hi,
>
> I followed the ejb3_example on the many to many annotations. Ended up
> with this
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
> xmlns:xlink="http://www.w3.org/1999/xlink"
> attributeFormDefault="unqualified" elementFormDefault="qualified"
> targetNamespace="http://www.stpware.com/secmsecurity"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
> <xsd:import schemaLocation="xml.xsd"
> namespace="http://www.w3.org/XML/1998/namespace" />
> <xsd:simpleType name="javaDate" ecore:instanceClass="java.util.Date">
> <xsd:restriction base="xsd:dateTime">
> </xsd:restriction>
> </xsd:simpleType>
> <xsd:complexType name="User">
> <xsd:annotation>
> <xsd:documentation>
> <xsd:p>The basic user entity. Kept simple, the Role attribute is
> just a string. 'Admin', 'Cleanse', 'ReadOnly' and 'CrudUser'</xsd:p>
> </xsd:documentation>
> </xsd:annotation>
> <xsd:sequence minOccurs="0" maxOccurs="1">
> <xsd:element name="userrole" type="xsd:IDREF"
> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
> ecore:opposite="user">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">
> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
> targetEntity="UserRole" mappedBy="user" indexed="false")
> @JoinTable(name="UserRole")
> </xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> </xsd:sequence>
> <xsd:attribute name="id" type="xsd:int">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">@Id
> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
> </xsd:annotation>
> </xsd:attribute>
> <xsd:attribute name="firstName" type="xsd:string" />
> <xsd:attribute name="surname" type="xsd:string" />
> <xsd:attribute name="email" type="xsd:string" />
> <xsd:attribute name="salutation" type="xsd:string" />
> <xsd:attribute name="loginName" type="xsd:string" />
> <xsd:attribute name="password" type="xsd:string" />
> <xsd:attribute name="phone" type="xsd:string" />
> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
> <xsd:attribute name="userStart" type="secmsec:javaDate" />
> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
> </xsd:complexType>
> <xsd:element name="user" type="secmsec:User">
> </xsd:element>
>
> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>
> <xsd:complexType name="Role">
> <xsd:sequence minOccurs="0" maxOccurs="1">
> <xsd:element name="userrole" type="xsd:IDREF"
> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
> ecore:opposite="role">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">
> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
> targetEntity="UserRole" mappedBy="role")
> </xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> </xsd:sequence>
> <xsd:attribute name="id" type="xsd:int">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">@Id
> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
> </xsd:annotation>
> </xsd:attribute>
> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
> </xsd:complexType>
>
> <xsd:complexType name="UserRole">
> <xsd:sequence>
> <xsd:element name="user" type="xsd:IDREF"
> ecore:reference="secmsec:User" maxOccurs="unbounded"
> ecore:opposite="userrole">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">
> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
> targetEntity="User" indexed="false")
> @JoinTable(name="UserRole")
> </xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> <xsd:element name="role" type="xsd:IDREF"
> ecore:reference="secmsec:Role" maxOccurs="unbounded"
> ecore:opposite="userrole">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa">
> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
> targetEntity="Role")
> </xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> </xsd:sequence>
> </xsd:complexType>
> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>
> </xsd:schema>
>
> This gives me the exception:
>
> Exception in thread "main"
> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
> Found Attribute Name but expected one of : Array End (}), = character,
> Comma (,).
> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
> targetEntity="UserRole" mappedBy="role")
> Current lexeme: PERSIST
> at
> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>
> at
> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>
> at
> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>
>
> It is very explicit, but I cannot see what is different in structure to
> the example.
>
> Thx.
>
> David
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org]]>Martin Taal2008-09-26T10:35:21-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423289/#msg_423289
In which case the example on ManyToMany on http://www.elver.org/hibernate/ejb3_examples.html is wrong.
Now that it generates it generates way too many tables for my liking.
I know to represent User >-< Role (many to many) I need one table, lets
call it UserRole, it has 2 columns, user_id and role_id. user_id joins
to User.id and role_id joins to Role.id
What I get is 3 tables:
userrole_role with columns - userrole, role userrole_idx
userole with columns - e_id, user, userrole
role_userrole with columns - role, userole, role_userole_idx
Is there a way to end up with a simpler schema? What advantages do these
3 tables give over a single table? If I have lot of many to many my
schema will be much larger and much more difficult for people to understand.
Thx,
David
Martin Taal wrote:
> Hi David,
> I think there should be a comma between MERGE and PERSIST in the cascade
> attribute.
>
> gr. Martin
>
> David Wynter wrote:
>> Hi,
>>
>> I followed the ejb3_example on the many to many annotations. Ended up
>> with this
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>> xmlns:xlink="http://www.w3.org/1999/xlink"
>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>> targetNamespace="http://www.stpware.com/secmsecurity"
>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>> <xsd:import schemaLocation="xml.xsd"
>> namespace="http://www.w3.org/XML/1998/namespace" />
>> <xsd:simpleType name="javaDate" ecore:instanceClass="java.util.Date">
>> <xsd:restriction base="xsd:dateTime">
>> </xsd:restriction>
>> </xsd:simpleType>
>> <xsd:complexType name="User">
>> <xsd:annotation>
>> <xsd:documentation>
>> <xsd:p>The basic user entity. Kept simple, the Role attribute
>> is just a string. 'Admin', 'Cleanse', 'ReadOnly' and 'CrudUser'</xsd:p>
>> </xsd:documentation>
>> </xsd:annotation>
>> <xsd:sequence minOccurs="0" maxOccurs="1">
>> <xsd:element name="userrole" type="xsd:IDREF"
>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>> ecore:opposite="user">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">
>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>> targetEntity="UserRole" mappedBy="user" indexed="false")
>> @JoinTable(name="UserRole")
>> </xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> </xsd:sequence>
>> <xsd:attribute name="id" type="xsd:int">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">@Id
>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>> </xsd:annotation>
>> </xsd:attribute>
>> <xsd:attribute name="firstName" type="xsd:string" />
>> <xsd:attribute name="surname" type="xsd:string" />
>> <xsd:attribute name="email" type="xsd:string" />
>> <xsd:attribute name="salutation" type="xsd:string" />
>> <xsd:attribute name="loginName" type="xsd:string" />
>> <xsd:attribute name="password" type="xsd:string" />
>> <xsd:attribute name="phone" type="xsd:string" />
>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>> </xsd:complexType>
>> <xsd:element name="user" type="secmsec:User">
>> </xsd:element>
>>
>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>
>> <xsd:complexType name="Role">
>> <xsd:sequence minOccurs="0" maxOccurs="1">
>> <xsd:element name="userrole" type="xsd:IDREF"
>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>> ecore:opposite="role">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">
>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>> targetEntity="UserRole" mappedBy="role")
>> </xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> </xsd:sequence>
>> <xsd:attribute name="id" type="xsd:int">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">@Id
>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>> </xsd:annotation>
>> </xsd:attribute>
>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>> </xsd:complexType>
>>
>> <xsd:complexType name="UserRole">
>> <xsd:sequence>
>> <xsd:element name="user" type="xsd:IDREF"
>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>> ecore:opposite="userrole">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">
>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>> targetEntity="User" indexed="false")
>> @JoinTable(name="UserRole")
>> </xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> <xsd:element name="role" type="xsd:IDREF"
>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>> ecore:opposite="userrole">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa">
>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>> targetEntity="Role")
>> </xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> </xsd:sequence>
>> </xsd:complexType>
>> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>>
>> </xsd:schema>
>>
>> This gives me the exception:
>>
>> Exception in thread "main"
>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>> Found Attribute Name but expected one of : Array End (}), = character,
>> Comma (,).
>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>> targetEntity="UserRole" mappedBy="role")
>> Current lexeme: PERSIST
>> at
>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>
>> at
>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>
>> at
>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>
>>
>> It is very explicit, but I cannot see what is different in structure
>> to the example.
>>
>> Thx.
>>
>> David
>
>]]>David Wynter2008-09-26T10:58:12-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423290/#msg_423290
Thanks for pointing that out, I have repaired that.
In your case afaics you have an explicit join type UserRole. So technically the reference from user
to userrole and from role to userrole are not manytomany but onetomany. Because you explicitly say
that is a manytomany you get three tables:
for the join between user and userrole
for userrole itself
for the join from role to userrole.
In case you had not explicitly modelled the join type then a manytomany is appropriate.
Changing the annotation to OneToMany will solve this for you.
The targetentity is not required in the manytomany/onetomany. Normally this is computed by Teneo.
Also I noticed that you had indexed="false" only on one side. If you don't need the index on any of
the associations then you can also
PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a idbag is used), or
PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a hibernate bag is used.
gr. Martin
David Wynter wrote:
> Hi,
>
> In which case the example on ManyToMany on
> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>
> Now that it generates it generates way too many tables for my liking.
>
> I know to represent User >-< Role (many to many) I need one table, lets
> call it UserRole, it has 2 columns, user_id and role_id. user_id joins
> to User.id and role_id joins to Role.id
>
> What I get is 3 tables:
> userrole_role with columns - userrole, role userrole_idx
> userole with columns - e_id, user, userrole
> role_userrole with columns - role, userole, role_userole_idx
>
> Is there a way to end up with a simpler schema? What advantages do these
> 3 tables give over a single table? If I have lot of many to many my
> schema will be much larger and much more difficult for people to
> understand.
>
> Thx,
>
>
> David
>
>
> Martin Taal wrote:
>> Hi David,
>> I think there should be a comma between MERGE and PERSIST in the
>> cascade attribute.
>>
>> gr. Martin
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>> I followed the ejb3_example on the many to many annotations. Ended up
>>> with this
>>>
>>> <?xml version="1.0" encoding="UTF-8"?>
>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>> <xsd:import schemaLocation="xml.xsd"
>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>> <xsd:simpleType name="javaDate" ecore:instanceClass="java.util.Date">
>>> <xsd:restriction base="xsd:dateTime">
>>> </xsd:restriction>
>>> </xsd:simpleType>
>>> <xsd:complexType name="User">
>>> <xsd:annotation>
>>> <xsd:documentation>
>>> <xsd:p>The basic user entity. Kept simple, the Role attribute
>>> is just a string. 'Admin', 'Cleanse', 'ReadOnly' and 'CrudUser'</xsd:p>
>>> </xsd:documentation>
>>> </xsd:annotation>
>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>> <xsd:element name="userrole" type="xsd:IDREF"
>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>> ecore:opposite="user">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">
>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>> @JoinTable(name="UserRole")
>>> </xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> </xsd:sequence>
>>> <xsd:attribute name="id" type="xsd:int">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">@Id
>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:attribute>
>>> <xsd:attribute name="firstName" type="xsd:string" />
>>> <xsd:attribute name="surname" type="xsd:string" />
>>> <xsd:attribute name="email" type="xsd:string" />
>>> <xsd:attribute name="salutation" type="xsd:string" />
>>> <xsd:attribute name="loginName" type="xsd:string" />
>>> <xsd:attribute name="password" type="xsd:string" />
>>> <xsd:attribute name="phone" type="xsd:string" />
>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>> </xsd:complexType>
>>> <xsd:element name="user" type="secmsec:User">
>>> </xsd:element>
>>>
>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>
>>> <xsd:complexType name="Role">
>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>> <xsd:element name="userrole" type="xsd:IDREF"
>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>> ecore:opposite="role">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">
>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>> targetEntity="UserRole" mappedBy="role")
>>> </xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> </xsd:sequence>
>>> <xsd:attribute name="id" type="xsd:int">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">@Id
>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:attribute>
>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>> </xsd:complexType>
>>>
>>> <xsd:complexType name="UserRole">
>>> <xsd:sequence>
>>> <xsd:element name="user" type="xsd:IDREF"
>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>> ecore:opposite="userrole">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">
>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>> targetEntity="User" indexed="false")
>>> @JoinTable(name="UserRole")
>>> </xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> <xsd:element name="role" type="xsd:IDREF"
>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>> ecore:opposite="userrole">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa">
>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>> targetEntity="Role")
>>> </xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> </xsd:sequence>
>>> </xsd:complexType>
>>> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>>>
>>> </xsd:schema>
>>>
>>> This gives me the exception:
>>>
>>> Exception in thread "main"
>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>> Found Attribute Name but expected one of : Array End (}), =
>>> character, Comma (,).
>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>> targetEntity="UserRole" mappedBy="role")
>>> Current lexeme: PERSIST
>>> at
>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>
>>> at
>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>
>>> at
>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>
>>>
>>> It is very explicit, but I cannot see what is different in structure
>>> to the example.
>>>
>>> Thx.
>>>
>>> David
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org]]>Martin Taal2008-09-26T11:29:36-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423301/#msg_423301
After reading the Hibernate manual a little I found this example for one
to many, many to one
What annotation would we use to achieve this configuration?
Thx.
David
Martin Taal wrote:
> Hi David,
> Thanks for pointing that out, I have repaired that.
>
> In your case afaics you have an explicit join type UserRole. So
> technically the reference from user to userrole and from role to
> userrole are not manytomany but onetomany. Because you explicitly say
> that is a manytomany you get three tables:
> for the join between user and userrole
> for userrole itself
> for the join from role to userrole.
>
> In case you had not explicitly modelled the join type then a manytomany
> is appropriate.
> Changing the annotation to OneToMany will solve this for you.
>
> The targetentity is not required in the manytomany/onetomany. Normally
> this is computed by Teneo.
>
> Also I noticed that you had indexed="false" only on one side. If you
> don't need the index on any of the associations then you can also
> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a idbag
> is used), or
> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
> hibernate bag is used.
>
> gr. Martin
>
> David Wynter wrote:
>> Hi,
>>
>> In which case the example on ManyToMany on
>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>
>> Now that it generates it generates way too many tables for my liking.
>>
>> I know to represent User >-< Role (many to many) I need one table,
>> lets call it UserRole, it has 2 columns, user_id and role_id. user_id
>> joins to User.id and role_id joins to Role.id
>>
>> What I get is 3 tables:
>> userrole_role with columns - userrole, role userrole_idx
>> userole with columns - e_id, user, userrole
>> role_userrole with columns - role, userole, role_userole_idx
>>
>> Is there a way to end up with a simpler schema? What advantages do
>> these 3 tables give over a single table? If I have lot of many to many
>> my schema will be much larger and much more difficult for people to
>> understand.
>>
>> Thx,
>>
>>
>> David
>>
>>
>> Martin Taal wrote:
>>> Hi David,
>>> I think there should be a comma between MERGE and PERSIST in the
>>> cascade attribute.
>>>
>>> gr. Martin
>>>
>>> David Wynter wrote:
>>>> Hi,
>>>>
>>>> I followed the ejb3_example on the many to many annotations. Ended
>>>> up with this
>>>>
>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>> <xsd:import schemaLocation="xml.xsd"
>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>> <xsd:simpleType name="javaDate"
>>>> ecore:instanceClass="java.util.Date">
>>>> <xsd:restriction base="xsd:dateTime">
>>>> </xsd:restriction>
>>>> </xsd:simpleType>
>>>> <xsd:complexType name="User">
>>>> <xsd:annotation>
>>>> <xsd:documentation>
>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>> 'CrudUser'</xsd:p>
>>>> </xsd:documentation>
>>>> </xsd:annotation>
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>> ecore:opposite="user">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>> @JoinTable(name="UserRole")
>>>> </xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> </xsd:sequence>
>>>> <xsd:attribute name="id" type="xsd:int">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:attribute>
>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>> <xsd:attribute name="email" type="xsd:string" />
>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>> <xsd:attribute name="password" type="xsd:string" />
>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>> </xsd:complexType>
>>>> <xsd:element name="user" type="secmsec:User">
>>>> </xsd:element>
>>>>
>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>
>>>> <xsd:complexType name="Role">
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>> ecore:opposite="role">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>> targetEntity="UserRole" mappedBy="role")
>>>> </xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> </xsd:sequence>
>>>> <xsd:attribute name="id" type="xsd:int">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:attribute>
>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>> </xsd:complexType>
>>>>
>>>> <xsd:complexType name="UserRole">
>>>> <xsd:sequence>
>>>> <xsd:element name="user" type="xsd:IDREF"
>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>> ecore:opposite="userrole">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>> targetEntity="User" indexed="false")
>>>> @JoinTable(name="UserRole")
>>>> </xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> <xsd:element name="role" type="xsd:IDREF"
>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>> ecore:opposite="userrole">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>> targetEntity="Role")
>>>> </xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> </xsd:sequence>
>>>> </xsd:complexType>
>>>> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>>>>
>>>> </xsd:schema>
>>>>
>>>> This gives me the exception:
>>>>
>>>> Exception in thread "main"
>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>> Found Attribute Name but expected one of : Array End (}), =
>>>> character, Comma (,).
>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>> targetEntity="UserRole" mappedBy="role")
>>>> Current lexeme: PERSIST
>>>> at
>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>
>>>> at
>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>
>>>> at
>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>
>>>>
>>>> It is very explicit, but I cannot see what is different in structure
>>>> to the example.
>>>>
>>>> Thx.
>>>>
>>>> David
>>>
>>>
>
>]]>David Wynter2008-09-26T16:15:26-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423305/#msg_423305
To be sure we are not discussing the User, UserRole, Role (whereby userrole is present as a separate
type) case anymore are we?
To get the result of what you want with hibernate add this annotation in the efeature which is the list:
@OneToMany(indexed=false, mappedBy="one")
@JoinTable(name="maniesofone")
where one is the opposite feature name.
Some other info:
Teneo as a default maps non-containment associations with a jointable (is controlled by the option:
PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
However, for bidirectional lists the many-to-one mapping creates an additional foreign key on the
many side. This because hibernate does not support bidirectional lists. To prevent this you should
also disable the mapping of the list index (see the map as bag and map as idbag in the other
replies, or used indexed="false").
So to summarize you can try to set the option PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and
then see where join tables are created.
Note that for a bidirectional one-to-many/many-to-one a join table is not strictly required because
the many is always only used once (as the relation is bidirectional).
gr. Martin
David Wynter wrote:
> Hi,
>
> After reading the Hibernate manual a little I found this example for one
> to many, many to one
>
> <class name="Person">
> <id name="id" column="personId">
> <generator class="native"/>
> </id>
> <set name="addresses"
> table="PersonAddress">
> <key column="personId"/>
> <many-to-many column="addressId"
> unique="true"
> class="Address"/>
> </set>
> </class>
>
> <class name="Address">
> <id name="id" column="addressId">
> <generator class="native"/>
> </id>
> <join table="PersonAddress"
> inverse="true"
> optional="true">
> <key column="addressId"/>
> <many-to-one name="person"
> column="personId"
> not-null="true"/>
> </join>
> </class>
>
> What annotation would we use to achieve this configuration?
>
> Thx.
>
> David
>
> Martin Taal wrote:
>> Hi David,
>> Thanks for pointing that out, I have repaired that.
>>
>> In your case afaics you have an explicit join type UserRole. So
>> technically the reference from user to userrole and from role to
>> userrole are not manytomany but onetomany. Because you explicitly say
>> that is a manytomany you get three tables:
>> for the join between user and userrole
>> for userrole itself
>> for the join from role to userrole.
>>
>> In case you had not explicitly modelled the join type then a
>> manytomany is appropriate.
>> Changing the annotation to OneToMany will solve this for you.
>>
>> The targetentity is not required in the manytomany/onetomany. Normally
>> this is computed by Teneo.
>>
>> Also I noticed that you had indexed="false" only on one side. If you
>> don't need the index on any of the associations then you can also
>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a idbag
>> is used), or
>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>> hibernate bag is used.
>>
>> gr. Martin
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>> In which case the example on ManyToMany on
>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>
>>> Now that it generates it generates way too many tables for my liking.
>>>
>>> I know to represent User >-< Role (many to many) I need one table,
>>> lets call it UserRole, it has 2 columns, user_id and role_id. user_id
>>> joins to User.id and role_id joins to Role.id
>>>
>>> What I get is 3 tables:
>>> userrole_role with columns - userrole, role userrole_idx
>>> userole with columns - e_id, user, userrole
>>> role_userrole with columns - role, userole, role_userole_idx
>>>
>>> Is there a way to end up with a simpler schema? What advantages do
>>> these 3 tables give over a single table? If I have lot of many to
>>> many my schema will be much larger and much more difficult for people
>>> to understand.
>>>
>>> Thx,
>>>
>>>
>>> David
>>>
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> I think there should be a comma between MERGE and PERSIST in the
>>>> cascade attribute.
>>>>
>>>> gr. Martin
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> I followed the ejb3_example on the many to many annotations. Ended
>>>>> up with this
>>>>>
>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>> <xsd:simpleType name="javaDate"
>>>>> ecore:instanceClass="java.util.Date">
>>>>> <xsd:restriction base="xsd:dateTime">
>>>>> </xsd:restriction>
>>>>> </xsd:simpleType>
>>>>> <xsd:complexType name="User">
>>>>> <xsd:annotation>
>>>>> <xsd:documentation>
>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>> 'CrudUser'</xsd:p>
>>>>> </xsd:documentation>
>>>>> </xsd:annotation>
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>> ecore:opposite="user">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>> @JoinTable(name="UserRole")
>>>>> </xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:attribute>
>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>> </xsd:complexType>
>>>>> <xsd:element name="user" type="secmsec:User">
>>>>> </xsd:element>
>>>>>
>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>
>>>>> <xsd:complexType name="Role">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>> ecore:opposite="role">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>> targetEntity="UserRole" mappedBy="role")
>>>>> </xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:attribute>
>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>> </xsd:complexType>
>>>>>
>>>>> <xsd:complexType name="UserRole">
>>>>> <xsd:sequence>
>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>> ecore:opposite="userrole">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>> targetEntity="User" indexed="false")
>>>>> @JoinTable(name="UserRole")
>>>>> </xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>> ecore:opposite="userrole">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>> targetEntity="Role")
>>>>> </xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> </xsd:complexType>
>>>>> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>>>>>
>>>>> </xsd:schema>
>>>>>
>>>>> This gives me the exception:
>>>>>
>>>>> Exception in thread "main"
>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>> character, Comma (,).
>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>> targetEntity="UserRole" mappedBy="role")
>>>>> Current lexeme: PERSIST
>>>>> at
>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>
>>>>> at
>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>
>>>>> at
>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>
>>>>>
>>>>> It is very explicit, but I cannot see what is different in
>>>>> structure to the example.
>>>>>
>>>>> Thx.
>>>>>
>>>>> David
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org]]>Martin Taal2008-09-26T17:22:17-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423379/#msg_423379
The suggestions you gave did generate the correct database tables. But I
am confused, as the generate methods do not reflect the underlying
tables. For example I have
Inside Group entity declaration we have
<bag name="groupUser" inverse="true" table="`usergroup`" lazy="true"
cascade="all,delete-orphan">
<key update="true">
<column name="`group_id`" not-null="true" unique="false"/>
</key>
<many-to-many entity-name="User" unique="true"
foreign-key="group_groupuser">
<column name="`user_id`" not-null="true" unique="false"/>
</many-to-many>
</bag>
Inside User declaration we have
<bag name="userGroup" inverse="true" table="`usergroup`" lazy="true"
cascade="all,delete-orphan">
<key update="true">
<column name="`user_id`" not-null="true" unique="false"/>
</key>
<many-to-many entity-name="Group" unique="true"
foreign-key="user_usergroup">
<column name="`group_id`" not-null="true" unique="false"/>
</many-to-many>
</bag>
But the generated User Interface has a method "Group getGroup();"
The generated Group Interface has "User getUser();"
This should be "EList<Group> getGroup();" and "Elist<User> getUser();"
shouldn't it?
Thx.
David
Martin Taal wrote:
> Hi David,
> To be sure we are not discussing the User, UserRole, Role (whereby
> userrole is present as a separate type) case anymore are we?
>
> To get the result of what you want with hibernate add this annotation in
> the efeature which is the list:
> @OneToMany(indexed=false, mappedBy="one")
> @JoinTable(name="maniesofone")
>
> where one is the opposite feature name.
>
> Some other info:
> Teneo as a default maps non-containment associations with a jointable
> (is controlled by the option:
> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
> However, for bidirectional lists the many-to-one mapping creates an
> additional foreign key on the many side. This because hibernate does not
> support bidirectional lists. To prevent this you should also disable the
> mapping of the list index (see the map as bag and map as idbag in the
> other replies, or used indexed="false").
>
> So to summarize you can try to set the option
> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see where
> join tables are created.
>
> Note that for a bidirectional one-to-many/many-to-one a join table is
> not strictly required because the many is always only used once (as the
> relation is bidirectional).
>
> gr. Martin
>
>
> David Wynter wrote:
>> Hi,
>>
>> After reading the Hibernate manual a little I found this example for
>> one to many, many to one
>>
>> <class name="Person">
>> <id name="id" column="personId">
>> <generator class="native"/>
>> </id>
>> <set name="addresses"
>> table="PersonAddress">
>> <key column="personId"/>
>> <many-to-many column="addressId"
>> unique="true"
>> class="Address"/>
>> </set>
>> </class>
>>
>> <class name="Address">
>> <id name="id" column="addressId">
>> <generator class="native"/>
>> </id>
>> <join table="PersonAddress"
>> inverse="true"
>> optional="true">
>> <key column="addressId"/>
>> <many-to-one name="person"
>> column="personId"
>> not-null="true"/>
>> </join>
>> </class>
>>
>> What annotation would we use to achieve this configuration?
>>
>> Thx.
>>
>> David
>>
>> Martin Taal wrote:
>>> Hi David,
>>> Thanks for pointing that out, I have repaired that.
>>>
>>> In your case afaics you have an explicit join type UserRole. So
>>> technically the reference from user to userrole and from role to
>>> userrole are not manytomany but onetomany. Because you explicitly say
>>> that is a manytomany you get three tables:
>>> for the join between user and userrole
>>> for userrole itself
>>> for the join from role to userrole.
>>>
>>> In case you had not explicitly modelled the join type then a
>>> manytomany is appropriate.
>>> Changing the annotation to OneToMany will solve this for you.
>>>
>>> The targetentity is not required in the manytomany/onetomany.
>>> Normally this is computed by Teneo.
>>>
>>> Also I noticed that you had indexed="false" only on one side. If you
>>> don't need the index on any of the associations then you can also
>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>> idbag is used), or
>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>> hibernate bag is used.
>>>
>>> gr. Martin
>>>
>>> David Wynter wrote:
>>>> Hi,
>>>>
>>>> In which case the example on ManyToMany on
>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>
>>>> Now that it generates it generates way too many tables for my liking.
>>>>
>>>> I know to represent User >-< Role (many to many) I need one table,
>>>> lets call it UserRole, it has 2 columns, user_id and role_id.
>>>> user_id joins to User.id and role_id joins to Role.id
>>>>
>>>> What I get is 3 tables:
>>>> userrole_role with columns - userrole, role userrole_idx
>>>> userole with columns - e_id, user, userrole
>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>
>>>> Is there a way to end up with a simpler schema? What advantages do
>>>> these 3 tables give over a single table? If I have lot of many to
>>>> many my schema will be much larger and much more difficult for
>>>> people to understand.
>>>>
>>>> Thx,
>>>>
>>>>
>>>> David
>>>>
>>>>
>>>> Martin Taal wrote:
>>>>> Hi David,
>>>>> I think there should be a comma between MERGE and PERSIST in the
>>>>> cascade attribute.
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> David Wynter wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I followed the ejb3_example on the many to many annotations. Ended
>>>>>> up with this
>>>>>>
>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>> <xsd:simpleType name="javaDate"
>>>>>> ecore:instanceClass="java.util.Date">
>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>> </xsd:restriction>
>>>>>> </xsd:simpleType>
>>>>>> <xsd:complexType name="User">
>>>>>> <xsd:annotation>
>>>>>> <xsd:documentation>
>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>>> 'CrudUser'</xsd:p>
>>>>>> </xsd:documentation>
>>>>>> </xsd:annotation>
>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>> ecore:opposite="user">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>> @JoinTable(name="UserRole")
>>>>>> </xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:element>
>>>>>> </xsd:sequence>
>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:attribute>
>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>> </xsd:complexType>
>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>> </xsd:element>
>>>>>>
>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>
>>>>>> <xsd:complexType name="Role">
>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>> ecore:opposite="role">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>> </xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:element>
>>>>>> </xsd:sequence>
>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:attribute>
>>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>>> </xsd:complexType>
>>>>>>
>>>>>> <xsd:complexType name="UserRole">
>>>>>> <xsd:sequence>
>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>> ecore:opposite="userrole">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>> targetEntity="User" indexed="false")
>>>>>> @JoinTable(name="UserRole")
>>>>>> </xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:element>
>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>> ecore:opposite="userrole">
>>>>>> <xsd:annotation>
>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>> targetEntity="Role")
>>>>>> </xsd:appinfo>
>>>>>> </xsd:annotation>
>>>>>> </xsd:element>
>>>>>> </xsd:sequence>
>>>>>> </xsd:complexType>
>>>>>> <xsd:element name="userrole" type="secmsec:UserRole"></xsd:element>
>>>>>>
>>>>>> </xsd:schema>
>>>>>>
>>>>>> This gives me the exception:
>>>>>>
>>>>>> Exception in thread "main"
>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>> character, Comma (,).
>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>> Current lexeme: PERSIST
>>>>>> at
>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>
>>>>>> at
>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>
>>>>>> at
>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>
>>>>>>
>>>>>> It is very explicit, but I cannot see what is different in
>>>>>> structure to the example.
>>>>>>
>>>>>> Thx.
>>>>>>
>>>>>> David
>>>>>
>>>>>
>>>
>>>
>
>]]>David Wynter2008-09-29T16:21:27-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423386/#msg_423386
I would expect that there is a method getGroupUser in Group returning an EList<User> and a
getUserGroup in User which returns an EList<Group>.
Did you reload the xsd in the genmodel and then regenerate the model code?
gr. Martin
David Wynter wrote:
> Hi,
>
> The suggestions you gave did generate the correct database tables. But I
> am confused, as the generate methods do not reflect the underlying
> tables. For example I have
>
> <xsd:complexType name="Group">
> <xsd:sequence minOccurs="0" maxOccurs="1">
> <xsd:element minOccurs="0" maxOccurs="unbounded" name="groupUser"
> type="secmsec:User" ecore:opposite="group">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
> mappedBy="user") @JoinTable(name="UserGroup")</xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> </xsd:sequence>
> ....
>
>
> <xsd:complexType name="User">
> <xsd:sequence minOccurs="0" maxOccurs="1">
> <xsd:element minOccurs="0" maxOccurs="unbounded"
> name="userGroup" type="secmsec:Group" ecore:opposite="user">
> <xsd:annotation>
> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
> mappedBy="group") @JoinTable(name="UserGroup")</xsd:appinfo>
> </xsd:annotation>
> </xsd:element>
> ....
>
>
> This generates the following hibernate.hbm.xml
>
> Inside Group entity declaration we have
> <bag name="groupUser" inverse="true" table="`usergroup`"
> lazy="true" cascade="all,delete-orphan">
> <key update="true">
> <column name="`group_id`" not-null="true" unique="false"/>
> </key>
> <many-to-many entity-name="User" unique="true"
> foreign-key="group_groupuser">
> <column name="`user_id`" not-null="true" unique="false"/>
> </many-to-many>
> </bag>
>
>
> Inside User declaration we have
> <bag name="userGroup" inverse="true" table="`usergroup`"
> lazy="true" cascade="all,delete-orphan">
> <key update="true">
> <column name="`user_id`" not-null="true" unique="false"/>
> </key>
> <many-to-many entity-name="Group" unique="true"
> foreign-key="user_usergroup">
> <column name="`group_id`" not-null="true" unique="false"/>
> </many-to-many>
> </bag>
>
> But the generated User Interface has a method "Group getGroup();"
> The generated Group Interface has "User getUser();"
>
> This should be "EList<Group> getGroup();" and "Elist<User> getUser();"
> shouldn't it?
>
> Thx.
>
> David
>
> Martin Taal wrote:
>> Hi David,
>> To be sure we are not discussing the User, UserRole, Role (whereby
>> userrole is present as a separate type) case anymore are we?
>>
>> To get the result of what you want with hibernate add this annotation
>> in the efeature which is the list:
>> @OneToMany(indexed=false, mappedBy="one")
>> @JoinTable(name="maniesofone")
>>
>> where one is the opposite feature name.
>>
>> Some other info:
>> Teneo as a default maps non-containment associations with a jointable
>> (is controlled by the option:
>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>> However, for bidirectional lists the many-to-one mapping creates an
>> additional foreign key on the many side. This because hibernate does
>> not support bidirectional lists. To prevent this you should also
>> disable the mapping of the list index (see the map as bag and map as
>> idbag in the other replies, or used indexed="false").
>>
>> So to summarize you can try to set the option
>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see where
>> join tables are created.
>>
>> Note that for a bidirectional one-to-many/many-to-one a join table is
>> not strictly required because the many is always only used once (as
>> the relation is bidirectional).
>>
>> gr. Martin
>>
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>> After reading the Hibernate manual a little I found this example for
>>> one to many, many to one
>>>
>>> <class name="Person">
>>> <id name="id" column="personId">
>>> <generator class="native"/>
>>> </id>
>>> <set name="addresses"
>>> table="PersonAddress">
>>> <key column="personId"/>
>>> <many-to-many column="addressId"
>>> unique="true"
>>> class="Address"/>
>>> </set>
>>> </class>
>>>
>>> <class name="Address">
>>> <id name="id" column="addressId">
>>> <generator class="native"/>
>>> </id>
>>> <join table="PersonAddress"
>>> inverse="true"
>>> optional="true">
>>> <key column="addressId"/>
>>> <many-to-one name="person"
>>> column="personId"
>>> not-null="true"/>
>>> </join>
>>> </class>
>>>
>>> What annotation would we use to achieve this configuration?
>>>
>>> Thx.
>>>
>>> David
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> Thanks for pointing that out, I have repaired that.
>>>>
>>>> In your case afaics you have an explicit join type UserRole. So
>>>> technically the reference from user to userrole and from role to
>>>> userrole are not manytomany but onetomany. Because you explicitly
>>>> say that is a manytomany you get three tables:
>>>> for the join between user and userrole
>>>> for userrole itself
>>>> for the join from role to userrole.
>>>>
>>>> In case you had not explicitly modelled the join type then a
>>>> manytomany is appropriate.
>>>> Changing the annotation to OneToMany will solve this for you.
>>>>
>>>> The targetentity is not required in the manytomany/onetomany.
>>>> Normally this is computed by Teneo.
>>>>
>>>> Also I noticed that you had indexed="false" only on one side. If you
>>>> don't need the index on any of the associations then you can also
>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>> idbag is used), or
>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>> hibernate bag is used.
>>>>
>>>> gr. Martin
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> In which case the example on ManyToMany on
>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>
>>>>> Now that it generates it generates way too many tables for my liking.
>>>>>
>>>>> I know to represent User >-< Role (many to many) I need one table,
>>>>> lets call it UserRole, it has 2 columns, user_id and role_id.
>>>>> user_id joins to User.id and role_id joins to Role.id
>>>>>
>>>>> What I get is 3 tables:
>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>> userole with columns - e_id, user, userrole
>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>
>>>>> Is there a way to end up with a simpler schema? What advantages do
>>>>> these 3 tables give over a single table? If I have lot of many to
>>>>> many my schema will be much larger and much more difficult for
>>>>> people to understand.
>>>>>
>>>>> Thx,
>>>>>
>>>>>
>>>>> David
>>>>>
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi David,
>>>>>> I think there should be a comma between MERGE and PERSIST in the
>>>>>> cascade attribute.
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> David Wynter wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>> Ended up with this
>>>>>>>
>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>> </xsd:restriction>
>>>>>>> </xsd:simpleType>
>>>>>>> <xsd:complexType name="User">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:documentation>
>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>>>> 'CrudUser'</xsd:p>
>>>>>>> </xsd:documentation>
>>>>>>> </xsd:annotation>
>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>> ecore:opposite="user">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>> @JoinTable(name="UserRole")
>>>>>>> </xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:element>
>>>>>>> </xsd:sequence>
>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:attribute>
>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>> </xsd:complexType>
>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>> </xsd:element>
>>>>>>>
>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>
>>>>>>> <xsd:complexType name="Role">
>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>> ecore:opposite="role">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>> </xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:element>
>>>>>>> </xsd:sequence>
>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:attribute>
>>>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>>>> </xsd:complexType>
>>>>>>>
>>>>>>> <xsd:complexType name="UserRole">
>>>>>>> <xsd:sequence>
>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>> ecore:opposite="userrole">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>> targetEntity="User" indexed="false")
>>>>>>> @JoinTable(name="UserRole")
>>>>>>> </xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:element>
>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>> ecore:opposite="userrole">
>>>>>>> <xsd:annotation>
>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>> targetEntity="Role")
>>>>>>> </xsd:appinfo>
>>>>>>> </xsd:annotation>
>>>>>>> </xsd:element>
>>>>>>> </xsd:sequence>
>>>>>>> </xsd:complexType>
>>>>>>> <xsd:element name="userrole"
>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>
>>>>>>> </xsd:schema>
>>>>>>>
>>>>>>> This gives me the exception:
>>>>>>>
>>>>>>> Exception in thread "main"
>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>> character, Comma (,).
>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>> Current lexeme: PERSIST
>>>>>>> at
>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>
>>>>>>> at
>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>
>>>>>>> at
>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>
>>>>>>>
>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>> structure to the example.
>>>>>>>
>>>>>>> Thx.
>>>>>>>
>>>>>>> David
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
This time I deleted the User and Group interface and classes. When I
generated it did indeed add the getUserGroup and getGroupUser methods
where expected.
The thing I did not expect was that the the Group.getUser() and
User.getGroup(), both returning a single object. I can just ignore these
but it is a little confusing to have them there.
regards,
David
Martin Taal wrote:
> Hi David,
> I would expect that there is a method getGroupUser in Group returning an
> EList<User> and a getUserGroup in User which returns an EList<Group>.
> Did you reload the xsd in the genmodel and then regenerate the model code?
>
> gr. Martin
>
>
> David Wynter wrote:
>> Hi,
>>
>> The suggestions you gave did generate the correct database tables. But
>> I am confused, as the generate methods do not reflect the underlying
>> tables. For example I have
>>
>> <xsd:complexType name="Group">
>> <xsd:sequence minOccurs="0" maxOccurs="1">
>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>> mappedBy="user") @JoinTable(name="UserGroup")</xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> </xsd:sequence>
>> ....
>>
>>
>> <xsd:complexType name="User">
>> <xsd:sequence minOccurs="0" maxOccurs="1">
>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>> <xsd:annotation>
>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>> mappedBy="group") @JoinTable(name="UserGroup")</xsd:appinfo>
>> </xsd:annotation>
>> </xsd:element>
>> ....
>>
>>
>> This generates the following hibernate.hbm.xml
>>
>> Inside Group entity declaration we have
>> <bag name="groupUser" inverse="true" table="`usergroup`"
>> lazy="true" cascade="all,delete-orphan">
>> <key update="true">
>> <column name="`group_id`" not-null="true"
>> unique="false"/>
>> </key>
>> <many-to-many entity-name="User" unique="true"
>> foreign-key="group_groupuser">
>> <column name="`user_id`" not-null="true" unique="false"/>
>> </many-to-many>
>> </bag>
>>
>>
>> Inside User declaration we have
>> <bag name="userGroup" inverse="true" table="`usergroup`"
>> lazy="true" cascade="all,delete-orphan">
>> <key update="true">
>> <column name="`user_id`" not-null="true" unique="false"/>
>> </key>
>> <many-to-many entity-name="Group" unique="true"
>> foreign-key="user_usergroup">
>> <column name="`group_id`" not-null="true"
>> unique="false"/>
>> </many-to-many>
>> </bag>
>>
>> But the generated User Interface has a method "Group getGroup();"
>> The generated Group Interface has "User getUser();"
>>
>> This should be "EList<Group> getGroup();" and "Elist<User> getUser();"
>> shouldn't it?
>>
>> Thx.
>>
>> David
>>
>> Martin Taal wrote:
>>> Hi David,
>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>> userrole is present as a separate type) case anymore are we?
>>>
>>> To get the result of what you want with hibernate add this annotation
>>> in the efeature which is the list:
>>> @OneToMany(indexed=false, mappedBy="one")
>>> @JoinTable(name="maniesofone")
>>>
>>> where one is the opposite feature name.
>>>
>>> Some other info:
>>> Teneo as a default maps non-containment associations with a jointable
>>> (is controlled by the option:
>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>> However, for bidirectional lists the many-to-one mapping creates an
>>> additional foreign key on the many side. This because hibernate does
>>> not support bidirectional lists. To prevent this you should also
>>> disable the mapping of the list index (see the map as bag and map as
>>> idbag in the other replies, or used indexed="false").
>>>
>>> So to summarize you can try to set the option
>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see where
>>> join tables are created.
>>>
>>> Note that for a bidirectional one-to-many/many-to-one a join table is
>>> not strictly required because the many is always only used once (as
>>> the relation is bidirectional).
>>>
>>> gr. Martin
>>>
>>>
>>> David Wynter wrote:
>>>> Hi,
>>>>
>>>> After reading the Hibernate manual a little I found this example for
>>>> one to many, many to one
>>>>
>>>> <class name="Person">
>>>> <id name="id" column="personId">
>>>> <generator class="native"/>
>>>> </id>
>>>> <set name="addresses"
>>>> table="PersonAddress">
>>>> <key column="personId"/>
>>>> <many-to-many column="addressId"
>>>> unique="true"
>>>> class="Address"/>
>>>> </set>
>>>> </class>
>>>>
>>>> <class name="Address">
>>>> <id name="id" column="addressId">
>>>> <generator class="native"/>
>>>> </id>
>>>> <join table="PersonAddress"
>>>> inverse="true"
>>>> optional="true">
>>>> <key column="addressId"/>
>>>> <many-to-one name="person"
>>>> column="personId"
>>>> not-null="true"/>
>>>> </join>
>>>> </class>
>>>>
>>>> What annotation would we use to achieve this configuration?
>>>>
>>>> Thx.
>>>>
>>>> David
>>>>
>>>> Martin Taal wrote:
>>>>> Hi David,
>>>>> Thanks for pointing that out, I have repaired that.
>>>>>
>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>> technically the reference from user to userrole and from role to
>>>>> userrole are not manytomany but onetomany. Because you explicitly
>>>>> say that is a manytomany you get three tables:
>>>>> for the join between user and userrole
>>>>> for userrole itself
>>>>> for the join from role to userrole.
>>>>>
>>>>> In case you had not explicitly modelled the join type then a
>>>>> manytomany is appropriate.
>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>
>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>> Normally this is computed by Teneo.
>>>>>
>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>> you don't need the index on any of the associations then you can also
>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>> idbag is used), or
>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>> hibernate bag is used.
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> David Wynter wrote:
>>>>>> Hi,
>>>>>>
>>>>>> In which case the example on ManyToMany on
>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>
>>>>>> Now that it generates it generates way too many tables for my liking.
>>>>>>
>>>>>> I know to represent User >-< Role (many to many) I need one table,
>>>>>> lets call it UserRole, it has 2 columns, user_id and role_id.
>>>>>> user_id joins to User.id and role_id joins to Role.id
>>>>>>
>>>>>> What I get is 3 tables:
>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>> userole with columns - e_id, user, userrole
>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>
>>>>>> Is there a way to end up with a simpler schema? What advantages do
>>>>>> these 3 tables give over a single table? If I have lot of many to
>>>>>> many my schema will be much larger and much more difficult for
>>>>>> people to understand.
>>>>>>
>>>>>> Thx,
>>>>>>
>>>>>>
>>>>>> David
>>>>>>
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> Hi David,
>>>>>>> I think there should be a comma between MERGE and PERSIST in the
>>>>>>> cascade attribute.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> David Wynter wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>> Ended up with this
>>>>>>>>
>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>> </xsd:restriction>
>>>>>>>> </xsd:simpleType>
>>>>>>>> <xsd:complexType name="User">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:documentation>
>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>>>>> 'CrudUser'</xsd:p>
>>>>>>>> </xsd:documentation>
>>>>>>>> </xsd:annotation>
>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>> ecore:opposite="user">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>> </xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:element>
>>>>>>>> </xsd:sequence>
>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:attribute>
>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>> </xsd:complexType>
>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>> </xsd:element>
>>>>>>>>
>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>
>>>>>>>> <xsd:complexType name="Role">
>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>> ecore:opposite="role">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>> </xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:element>
>>>>>>>> </xsd:sequence>
>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:attribute>
>>>>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>>>>> </xsd:complexType>
>>>>>>>>
>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>> <xsd:sequence>
>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>> ecore:opposite="userrole">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>> </xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:element>
>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>> ecore:opposite="userrole">
>>>>>>>> <xsd:annotation>
>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>> targetEntity="Role")
>>>>>>>> </xsd:appinfo>
>>>>>>>> </xsd:annotation>
>>>>>>>> </xsd:element>
>>>>>>>> </xsd:sequence>
>>>>>>>> </xsd:complexType>
>>>>>>>> <xsd:element name="userrole"
>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>
>>>>>>>> </xsd:schema>
>>>>>>>>
>>>>>>>> This gives me the exception:
>>>>>>>>
>>>>>>>> Exception in thread "main"
>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>> character, Comma (,).
>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>> Current lexeme: PERSIST
>>>>>>>> at
>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>
>>>>>>>> at
>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>
>>>>>>>> at
>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>
>>>>>>>>
>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>> structure to the example.
>>>>>>>>
>>>>>>>> Thx.
>>>>>>>>
>>>>>>>> David
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>]]>David Wynter2008-09-29T18:06:42-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423388/#msg_423388
Normally EMF should regenerate the code without the need to delete the classes/interfaces. Also I
can't really imagine that the getUser or getGroup originate from the two multi-occurence element you
showed below.
Maybe because there is a sequence with minOccurs="0" that you get these, but I can't really
understand why. (maybe Ed knows)
You can also check the ecore to see if Group has a user efeature (and User a group efeature). Then
when importing the xsd in the genmodel I think you can specify somewhere to generate a xsd2ecore
map. This generates an extra file, if you open that file then you can see the relation between the
ecore model elements and their corresponding xsd element. This could give more info.
gr. Martin
David Wynter wrote:
> Hi,
>
>
> This time I deleted the User and Group interface and classes. When I
> generated it did indeed add the getUserGroup and getGroupUser methods
> where expected.
>
> The thing I did not expect was that the the Group.getUser() and
> User.getGroup(), both returning a single object. I can just ignore these
> but it is a little confusing to have them there.
>
> regards,
>
> David
>
> Martin Taal wrote:
>> Hi David,
>> I would expect that there is a method getGroupUser in Group returning
>> an EList<User> and a getUserGroup in User which returns an EList<Group>.
>> Did you reload the xsd in the genmodel and then regenerate the model
>> code?
>>
>> gr. Martin
>>
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>> The suggestions you gave did generate the correct database tables.
>>> But I am confused, as the generate methods do not reflect the
>>> underlying tables. For example I have
>>>
>>> <xsd:complexType name="Group">
>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>>> mappedBy="user") @JoinTable(name="UserGroup")</xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> </xsd:sequence>
>>> ....
>>>
>>>
>>> <xsd:complexType name="User">
>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>> <xsd:annotation>
>>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>>> mappedBy="group") @JoinTable(name="UserGroup")</xsd:appinfo>
>>> </xsd:annotation>
>>> </xsd:element>
>>> ....
>>>
>>>
>>> This generates the following hibernate.hbm.xml
>>>
>>> Inside Group entity declaration we have
>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>> lazy="true" cascade="all,delete-orphan">
>>> <key update="true">
>>> <column name="`group_id`" not-null="true"
>>> unique="false"/>
>>> </key>
>>> <many-to-many entity-name="User" unique="true"
>>> foreign-key="group_groupuser">
>>> <column name="`user_id`" not-null="true"
>>> unique="false"/>
>>> </many-to-many>
>>> </bag>
>>>
>>>
>>> Inside User declaration we have
>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>> lazy="true" cascade="all,delete-orphan">
>>> <key update="true">
>>> <column name="`user_id`" not-null="true"
>>> unique="false"/>
>>> </key>
>>> <many-to-many entity-name="Group" unique="true"
>>> foreign-key="user_usergroup">
>>> <column name="`group_id`" not-null="true"
>>> unique="false"/>
>>> </many-to-many>
>>> </bag>
>>>
>>> But the generated User Interface has a method "Group getGroup();"
>>> The generated Group Interface has "User getUser();"
>>>
>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>> getUser();" shouldn't it?
>>>
>>> Thx.
>>>
>>> David
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>> userrole is present as a separate type) case anymore are we?
>>>>
>>>> To get the result of what you want with hibernate add this
>>>> annotation in the efeature which is the list:
>>>> @OneToMany(indexed=false, mappedBy="one")
>>>> @JoinTable(name="maniesofone")
>>>>
>>>> where one is the opposite feature name.
>>>>
>>>> Some other info:
>>>> Teneo as a default maps non-containment associations with a
>>>> jointable (is controlled by the option:
>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>> However, for bidirectional lists the many-to-one mapping creates an
>>>> additional foreign key on the many side. This because hibernate does
>>>> not support bidirectional lists. To prevent this you should also
>>>> disable the mapping of the list index (see the map as bag and map as
>>>> idbag in the other replies, or used indexed="false").
>>>>
>>>> So to summarize you can try to set the option
>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see where
>>>> join tables are created.
>>>>
>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>> is not strictly required because the many is always only used once
>>>> (as the relation is bidirectional).
>>>>
>>>> gr. Martin
>>>>
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> After reading the Hibernate manual a little I found this example
>>>>> for one to many, many to one
>>>>>
>>>>> <class name="Person">
>>>>> <id name="id" column="personId">
>>>>> <generator class="native"/>
>>>>> </id>
>>>>> <set name="addresses"
>>>>> table="PersonAddress">
>>>>> <key column="personId"/>
>>>>> <many-to-many column="addressId"
>>>>> unique="true"
>>>>> class="Address"/>
>>>>> </set>
>>>>> </class>
>>>>>
>>>>> <class name="Address">
>>>>> <id name="id" column="addressId">
>>>>> <generator class="native"/>
>>>>> </id>
>>>>> <join table="PersonAddress"
>>>>> inverse="true"
>>>>> optional="true">
>>>>> <key column="addressId"/>
>>>>> <many-to-one name="person"
>>>>> column="personId"
>>>>> not-null="true"/>
>>>>> </join>
>>>>> </class>
>>>>>
>>>>> What annotation would we use to achieve this configuration?
>>>>>
>>>>> Thx.
>>>>>
>>>>> David
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi David,
>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>
>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>> technically the reference from user to userrole and from role to
>>>>>> userrole are not manytomany but onetomany. Because you explicitly
>>>>>> say that is a manytomany you get three tables:
>>>>>> for the join between user and userrole
>>>>>> for userrole itself
>>>>>> for the join from role to userrole.
>>>>>>
>>>>>> In case you had not explicitly modelled the join type then a
>>>>>> manytomany is appropriate.
>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>
>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>> Normally this is computed by Teneo.
>>>>>>
>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>> you don't need the index on any of the associations then you can also
>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>> idbag is used), or
>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>> hibernate bag is used.
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> David Wynter wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> In which case the example on ManyToMany on
>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>
>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>> liking.
>>>>>>>
>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>
>>>>>>> What I get is 3 tables:
>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>> userole with columns - e_id, user, userrole
>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>
>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>> do these 3 tables give over a single table? If I have lot of many
>>>>>>> to many my schema will be much larger and much more difficult for
>>>>>>> people to understand.
>>>>>>>
>>>>>>> Thx,
>>>>>>>
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> Hi David,
>>>>>>>> I think there should be a comma between MERGE and PERSIST in the
>>>>>>>> cascade attribute.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> David Wynter wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>> Ended up with this
>>>>>>>>>
>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>> <xsd:schema xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>> </xsd:restriction>
>>>>>>>>> </xsd:simpleType>
>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:documentation>
>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>>>>>> 'CrudUser'</xsd:p>
>>>>>>>>> </xsd:documentation>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>> ecore:opposite="user">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>> </xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:element>
>>>>>>>>> </xsd:sequence>
>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:attribute>
>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>> </xsd:complexType>
>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>> </xsd:element>
>>>>>>>>>
>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>
>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>> ecore:opposite="role">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>> </xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:element>
>>>>>>>>> </xsd:sequence>
>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:attribute>
>>>>>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>>>>>> </xsd:complexType>
>>>>>>>>>
>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>> <xsd:sequence>
>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>> </xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:element>
>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>> <xsd:annotation>
>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>> targetEntity="Role")
>>>>>>>>> </xsd:appinfo>
>>>>>>>>> </xsd:annotation>
>>>>>>>>> </xsd:element>
>>>>>>>>> </xsd:sequence>
>>>>>>>>> </xsd:complexType>
>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>
>>>>>>>>> </xsd:schema>
>>>>>>>>>
>>>>>>>>> This gives me the exception:
>>>>>>>>>
>>>>>>>>> Exception in thread "main"
>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>> character, Comma (,).
>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>> at
>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>
>>>>>>>>> at
>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>
>>>>>>>>> at
>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>> structure to the example.
>>>>>>>>>
>>>>>>>>> Thx.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
Martin Taal wrote:
> Hi David,
> Normally EMF should regenerate the code without the need to delete the
> classes/interfaces. Also I can't really imagine that the getUser or
> getGroup originate from the two multi-occurence element you showed below.
They originate from the "ecore:opposite" annotations. The opposite of a
containment feature is a container feature and you can have at most one
container.
> Maybe because there is a sequence with minOccurs="0" that you get
> these, but I can't really understand why. (maybe Ed knows)
>
> You can also check the ecore to see if Group has a user efeature (and
> User a group efeature). Then when importing the xsd in the genmodel I
> think you can specify somewhere to generate a xsd2ecore map. This
> generates an extra file, if you open that file then you can see the
> relation between the ecore model elements and their corresponding xsd
> element. This could give more info.
>
> gr. Martin
>
> David Wynter wrote:
>> Hi,
>>
>>
>> This time I deleted the User and Group interface and classes. When I
>> generated it did indeed add the getUserGroup and getGroupUser methods
>> where expected.
>>
>> The thing I did not expect was that the the Group.getUser() and
>> User.getGroup(), both returning a single object. I can just ignore
>> these but it is a little confusing to have them there.
>>
>> regards,
>>
>> David
>>
>> Martin Taal wrote:
>>> Hi David,
>>> I would expect that there is a method getGroupUser in Group
>>> returning an EList<User> and a getUserGroup in User which returns an
>>> EList<Group>.
>>> Did you reload the xsd in the genmodel and then regenerate the model
>>> code?
>>>
>>> gr. Martin
>>>
>>>
>>> David Wynter wrote:
>>>> Hi,
>>>>
>>>> The suggestions you gave did generate the correct database tables.
>>>> But I am confused, as the generate methods do not reflect the
>>>> underlying tables. For example I have
>>>>
>>>> <xsd:complexType name="Group">
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @OneToMany(indexed=false, mappedBy="user")
>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> </xsd:sequence>
>>>> ....
>>>>
>>>>
>>>> <xsd:complexType name="User">
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa">
>>>> @OneToMany(indexed=false, mappedBy="group")
>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> ....
>>>>
>>>>
>>>> This generates the following hibernate.hbm.xml
>>>>
>>>> Inside Group entity declaration we have
>>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>>> lazy="true" cascade="all,delete-orphan">
>>>> <key update="true">
>>>> <column name="`group_id`" not-null="true"
>>>> unique="false"/>
>>>> </key>
>>>> <many-to-many entity-name="User" unique="true"
>>>> foreign-key="group_groupuser">
>>>> <column name="`user_id`" not-null="true"
>>>> unique="false"/>
>>>> </many-to-many>
>>>> </bag>
>>>>
>>>>
>>>> Inside User declaration we have
>>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>>> lazy="true" cascade="all,delete-orphan">
>>>> <key update="true">
>>>> <column name="`user_id`" not-null="true"
>>>> unique="false"/>
>>>> </key>
>>>> <many-to-many entity-name="Group" unique="true"
>>>> foreign-key="user_usergroup">
>>>> <column name="`group_id`" not-null="true"
>>>> unique="false"/>
>>>> </many-to-many>
>>>> </bag>
>>>>
>>>> But the generated User Interface has a method "Group getGroup();"
>>>> The generated Group Interface has "User getUser();"
>>>>
>>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>>> getUser();" shouldn't it?
>>>>
>>>> Thx.
>>>>
>>>> David
>>>>
>>>> Martin Taal wrote:
>>>>> Hi David,
>>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>>> userrole is present as a separate type) case anymore are we?
>>>>>
>>>>> To get the result of what you want with hibernate add this
>>>>> annotation in the efeature which is the list:
>>>>> @OneToMany(indexed=false, mappedBy="one")
>>>>> @JoinTable(name="maniesofone")
>>>>>
>>>>> where one is the opposite feature name.
>>>>>
>>>>> Some other info:
>>>>> Teneo as a default maps non-containment associations with a
>>>>> jointable (is controlled by the option:
>>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>>> However, for bidirectional lists the many-to-one mapping creates
>>>>> an additional foreign key on the many side. This because hibernate
>>>>> does not support bidirectional lists. To prevent this you should
>>>>> also disable the mapping of the list index (see the map as bag and
>>>>> map as idbag in the other replies, or used indexed="false").
>>>>>
>>>>> So to summarize you can try to set the option
>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see
>>>>> where join tables are created.
>>>>>
>>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>>> is not strictly required because the many is always only used once
>>>>> (as the relation is bidirectional).
>>>>>
>>>>> gr. Martin
>>>>>
>>>>>
>>>>> David Wynter wrote:
>>>>>> Hi,
>>>>>>
>>>>>> After reading the Hibernate manual a little I found this example
>>>>>> for one to many, many to one
>>>>>>
>>>>>> <class name="Person">
>>>>>> <id name="id" column="personId">
>>>>>> <generator class="native"/>
>>>>>> </id>
>>>>>> <set name="addresses"
>>>>>> table="PersonAddress">
>>>>>> <key column="personId"/>
>>>>>> <many-to-many column="addressId"
>>>>>> unique="true"
>>>>>> class="Address"/>
>>>>>> </set>
>>>>>> </class>
>>>>>>
>>>>>> <class name="Address">
>>>>>> <id name="id" column="addressId">
>>>>>> <generator class="native"/>
>>>>>> </id>
>>>>>> <join table="PersonAddress"
>>>>>> inverse="true"
>>>>>> optional="true">
>>>>>> <key column="addressId"/>
>>>>>> <many-to-one name="person"
>>>>>> column="personId"
>>>>>> not-null="true"/>
>>>>>> </join>
>>>>>> </class>
>>>>>>
>>>>>> What annotation would we use to achieve this configuration?
>>>>>>
>>>>>> Thx.
>>>>>>
>>>>>> David
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> Hi David,
>>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>>
>>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>>> technically the reference from user to userrole and from role to
>>>>>>> userrole are not manytomany but onetomany. Because you
>>>>>>> explicitly say that is a manytomany you get three tables:
>>>>>>> for the join between user and userrole
>>>>>>> for userrole itself
>>>>>>> for the join from role to userrole.
>>>>>>>
>>>>>>> In case you had not explicitly modelled the join type then a
>>>>>>> manytomany is appropriate.
>>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>>
>>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>>> Normally this is computed by Teneo.
>>>>>>>
>>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>>> you don't need the index on any of the associations then you can
>>>>>>> also
>>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>>> idbag is used), or
>>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>>> hibernate bag is used.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> David Wynter wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> In which case the example on ManyToMany on
>>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>>
>>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>>> liking.
>>>>>>>>
>>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>>
>>>>>>>> What I get is 3 tables:
>>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>>> userole with columns - e_id, user, userrole
>>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>>
>>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>>> do these 3 tables give over a single table? If I have lot of
>>>>>>>> many to many my schema will be much larger and much more
>>>>>>>> difficult for people to understand.
>>>>>>>>
>>>>>>>> Thx,
>>>>>>>>
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>>
>>>>>>>> Martin Taal wrote:
>>>>>>>>> Hi David,
>>>>>>>>> I think there should be a comma between MERGE and PERSIST in
>>>>>>>>> the cascade attribute.
>>>>>>>>>
>>>>>>>>> gr. Martin
>>>>>>>>>
>>>>>>>>> David Wynter wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>>> Ended up with this
>>>>>>>>>>
>>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>>> <xsd:schema
>>>>>>>>>> xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>>> attributeFormDefault="unqualified"
>>>>>>>>>> elementFormDefault="qualified"
>>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>>> </xsd:restriction>
>>>>>>>>>> </xsd:simpleType>
>>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:documentation>
>>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly'
>>>>>>>>>> and 'CrudUser'</xsd:p>
>>>>>>>>>> </xsd:documentation>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="user">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:attribute>
>>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>>> </xsd:element>
>>>>>>>>>>
>>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>>
>>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="role">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:attribute>
>>>>>>>>>> <xsd:attribute name="name"
>>>>>>>>>> type="xsd:string"></xsd:attribute>
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>
>>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>>> <xsd:sequence>
>>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="Role")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>>
>>>>>>>>>> </xsd:schema>
>>>>>>>>>>
>>>>>>>>>> This gives me the exception:
>>>>>>>>>>
>>>>>>>>>> Exception in thread "main"
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>>> character, Comma (,).
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>>
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>>
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>>> structure to the example.
>>>>>>>>>>
>>>>>>>>>> Thx.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>]]>Ed Merks2008-09-29T19:03:11-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423392/#msg_423392
You are right! Hmm, that I missed that one :-(...
gr. Martin
Ed Merks wrote:
> Martin,
>
> Comments below.
>
>
> Martin Taal wrote:
>> Hi David,
>> Normally EMF should regenerate the code without the need to delete the
>> classes/interfaces. Also I can't really imagine that the getUser or
>> getGroup originate from the two multi-occurence element you showed below.
> They originate from the "ecore:opposite" annotations. The opposite of a
> containment feature is a container feature and you can have at most one
> container.
>> Maybe because there is a sequence with minOccurs="0" that you get
>> these, but I can't really understand why. (maybe Ed knows)
>>
>> You can also check the ecore to see if Group has a user efeature (and
>> User a group efeature). Then when importing the xsd in the genmodel I
>> think you can specify somewhere to generate a xsd2ecore map. This
>> generates an extra file, if you open that file then you can see the
>> relation between the ecore model elements and their corresponding xsd
>> element. This could give more info.
>>
>> gr. Martin
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>>
>>> This time I deleted the User and Group interface and classes. When I
>>> generated it did indeed add the getUserGroup and getGroupUser methods
>>> where expected.
>>>
>>> The thing I did not expect was that the the Group.getUser() and
>>> User.getGroup(), both returning a single object. I can just ignore
>>> these but it is a little confusing to have them there.
>>>
>>> regards,
>>>
>>> David
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> I would expect that there is a method getGroupUser in Group
>>>> returning an EList<User> and a getUserGroup in User which returns an
>>>> EList<Group>.
>>>> Did you reload the xsd in the genmodel and then regenerate the model
>>>> code?
>>>>
>>>> gr. Martin
>>>>
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> The suggestions you gave did generate the correct database tables.
>>>>> But I am confused, as the generate methods do not reflect the
>>>>> underlying tables. For example I have
>>>>>
>>>>> <xsd:complexType name="Group">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="user")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> ....
>>>>>
>>>>>
>>>>> <xsd:complexType name="User">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="group")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> ....
>>>>>
>>>>>
>>>>> This generates the following hibernate.hbm.xml
>>>>>
>>>>> Inside Group entity declaration we have
>>>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="User" unique="true"
>>>>> foreign-key="group_groupuser">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>>
>>>>> Inside User declaration we have
>>>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="Group" unique="true"
>>>>> foreign-key="user_usergroup">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>> But the generated User Interface has a method "Group getGroup();"
>>>>> The generated Group Interface has "User getUser();"
>>>>>
>>>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>>>> getUser();" shouldn't it?
>>>>>
>>>>> Thx.
>>>>>
>>>>> David
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi David,
>>>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>>>> userrole is present as a separate type) case anymore are we?
>>>>>>
>>>>>> To get the result of what you want with hibernate add this
>>>>>> annotation in the efeature which is the list:
>>>>>> @OneToMany(indexed=false, mappedBy="one")
>>>>>> @JoinTable(name="maniesofone")
>>>>>>
>>>>>> where one is the opposite feature name.
>>>>>>
>>>>>> Some other info:
>>>>>> Teneo as a default maps non-containment associations with a
>>>>>> jointable (is controlled by the option:
>>>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>>>> However, for bidirectional lists the many-to-one mapping creates
>>>>>> an additional foreign key on the many side. This because hibernate
>>>>>> does not support bidirectional lists. To prevent this you should
>>>>>> also disable the mapping of the list index (see the map as bag and
>>>>>> map as idbag in the other replies, or used indexed="false").
>>>>>>
>>>>>> So to summarize you can try to set the option
>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see
>>>>>> where join tables are created.
>>>>>>
>>>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>>>> is not strictly required because the many is always only used once
>>>>>> (as the relation is bidirectional).
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>>
>>>>>> David Wynter wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> After reading the Hibernate manual a little I found this example
>>>>>>> for one to many, many to one
>>>>>>>
>>>>>>> <class name="Person">
>>>>>>> <id name="id" column="personId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <set name="addresses"
>>>>>>> table="PersonAddress">
>>>>>>> <key column="personId"/>
>>>>>>> <many-to-many column="addressId"
>>>>>>> unique="true"
>>>>>>> class="Address"/>
>>>>>>> </set>
>>>>>>> </class>
>>>>>>>
>>>>>>> <class name="Address">
>>>>>>> <id name="id" column="addressId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <join table="PersonAddress"
>>>>>>> inverse="true"
>>>>>>> optional="true">
>>>>>>> <key column="addressId"/>
>>>>>>> <many-to-one name="person"
>>>>>>> column="personId"
>>>>>>> not-null="true"/>
>>>>>>> </join>
>>>>>>> </class>
>>>>>>>
>>>>>>> What annotation would we use to achieve this configuration?
>>>>>>>
>>>>>>> Thx.
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> Hi David,
>>>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>>>
>>>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>>>> technically the reference from user to userrole and from role to
>>>>>>>> userrole are not manytomany but onetomany. Because you
>>>>>>>> explicitly say that is a manytomany you get three tables:
>>>>>>>> for the join between user and userrole
>>>>>>>> for userrole itself
>>>>>>>> for the join from role to userrole.
>>>>>>>>
>>>>>>>> In case you had not explicitly modelled the join type then a
>>>>>>>> manytomany is appropriate.
>>>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>>>
>>>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>>>> Normally this is computed by Teneo.
>>>>>>>>
>>>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>>>> you don't need the index on any of the associations then you can
>>>>>>>> also
>>>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>>>> idbag is used), or
>>>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>>>> hibernate bag is used.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> David Wynter wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> In which case the example on ManyToMany on
>>>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>>>
>>>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>>>> liking.
>>>>>>>>>
>>>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>>>
>>>>>>>>> What I get is 3 tables:
>>>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>>>> userole with columns - e_id, user, userrole
>>>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>>>
>>>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>>>> do these 3 tables give over a single table? If I have lot of
>>>>>>>>> many to many my schema will be much larger and much more
>>>>>>>>> difficult for people to understand.
>>>>>>>>>
>>>>>>>>> Thx,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Martin Taal wrote:
>>>>>>>>>> Hi David,
>>>>>>>>>> I think there should be a comma between MERGE and PERSIST in
>>>>>>>>>> the cascade attribute.
>>>>>>>>>>
>>>>>>>>>> gr. Martin
>>>>>>>>>>
>>>>>>>>>> David Wynter wrote:
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>>>> Ended up with this
>>>>>>>>>>>
>>>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>>>> <xsd:schema
>>>>>>>>>>> xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>>>> attributeFormDefault="unqualified"
>>>>>>>>>>> elementFormDefault="qualified"
>>>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>>>> </xsd:restriction>
>>>>>>>>>>> </xsd:simpleType>
>>>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:documentation>
>>>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly'
>>>>>>>>>>> and 'CrudUser'</xsd:p>
>>>>>>>>>>> </xsd:documentation>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="user">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="role">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="name"
>>>>>>>>>>> type="xsd:string"></xsd:attribute>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>>>> <xsd:sequence>
>>>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="Role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> </xsd:schema>
>>>>>>>>>>>
>>>>>>>>>>> This gives me the exception:
>>>>>>>>>>>
>>>>>>>>>>> Exception in thread "main"
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>>>> character, Comma (,).
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>>>> structure to the example.
>>>>>>>>>>>
>>>>>>>>>>> Thx.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org]]>Martin Taal2008-09-29T19:21:26-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423413/#msg_423413
See the answer of Ed one or two posts back. The getGroup and getUser are generated because there is
an eopposite defined.
gr. Martin
David Wynter wrote:
> Hi,
>
> I added the option to create the xsd2ecore map. Here are the relevant
> parts. I cannot see what there is in this that suggests that the Group
> getGroup() would be generated on the User interface.
>
>
> ....
> <nested inputs="secmsecurity.xsd#//User;XSDComplexTypeDefinition"
> outputs="secmsecurity.ecore#//User">
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDParticle /XSDModelGroup/XSDParticle "
>
> outputs="secmsecurity.ecore#//User/userPref"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDParticle /XSDModelGroup/XSDParticle=1 "
>
> outputs="secmsecurity.ecore#//User/userGroup"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDParticle /XSDModelGroup/XSDParticle=2 "
>
> outputs="secmsecurity.ecore#//User/userRole"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=3 "
> outputs="secmsecurity.ecore#//User/email"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=1 "
> outputs="secmsecurity.ecore#//User/firstName"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse "
> outputs="secmsecurity.ecore#//User/id"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=8 "
> outputs="secmsecurity.ecore#//User/lastLogin"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=5 "
> outputs="secmsecurity.ecore#//User/loginName"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=6 "
> outputs="secmsecurity.ecore#//User/password"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=7 "
> outputs="secmsecurity.ecore#//User/phone"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=4 "
> outputs="secmsecurity.ecore#//User/salutation"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=2 "
> outputs="secmsecurity.ecore#//User/surname"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=10 "
>
> outputs="secmsecurity.ecore#//User/userEnd"/>
> <nested
> inputs=" secmsecurity.xsd#//User;XSDComplexTypeDefinition/XSDAttribut eUse=9 "
> outputs="secmsecurity.ecore#//User/userStart"/>
> </nested>
> <nested inputs="secmsecurity.xsd#//Group;XSDComplexTypeDefinition=4 "
> outputs="secmsecurity.ecore#//Group">
> <nested
> inputs=" secmsecurity.xsd#//Group;XSDComplexTypeDefinition=4/XSDParti cle/XSDModelGroup/XSDParticle "
>
> outputs="secmsecurity.ecore#//Group/groupUser"/>
> <nested
> inputs=" secmsecurity.xsd#//Group;XSDComplexTypeDefinition=4/XSDAttri buteUse "
>
> outputs="secmsecurity.ecore#//Group/id"/>
> <nested
> inputs=" secmsecurity.xsd#//Group;XSDComplexTypeDefinition=4/XSDAttri buteUse=1 "
>
> outputs="secmsecurity.ecore#//Group/name"/>
> </nested>
> <nested inputs="secmsecurity.xsd#//group;XSDElementDeclaration=4"
> outputs="secmsecurity.ecore#//DocumentRoot/group"/>
> <nested inputs="secmsecurity.xsd#//permission;XSDElementDeclaration=3 "
> outputs="secmsecurity.ecore#//DocumentRoot/permission"/>
> <nested inputs="secmsecurity.xsd#//role;XSDElementDeclaration=2"
> outputs="secmsecurity.ecore#//DocumentRoot/role"/>
> <nested inputs="secmsecurity.xsd#//user;XSDElementDeclaration"
> outputs="secmsecurity.ecore#//DocumentRoot/user"/>
> <nested inputs="secmsecurity.xsd#//userPref;XSDElementDeclaration=1 "
> outputs="secmsecurity.ecore#//DocumentRoot/userPref"/>
> ....
>
> The ecore User does have an eFeature for the Group as well as one for
> the userGroup. The ecore Group does have an efeature for the User and
> the valid one for the groupUser.
>
> Changing the sequence to minOccurs and maxOccurs = 1 makes no difference
> in the outcome.
>
> Thx.
>
> David
>
> Martin Taal wrote:
>> Hi David,
>> Normally EMF should regenerate the code without the need to delete the
>> classes/interfaces. Also I can't really imagine that the getUser or
>> getGroup originate from the two multi-occurence element you showed below.
>> Maybe because there is a sequence with minOccurs="0" that you get
>> these, but I can't really understand why. (maybe Ed knows)
>>
>> You can also check the ecore to see if Group has a user efeature (and
>> User a group efeature). Then when importing the xsd in the genmodel I
>> think you can specify somewhere to generate a xsd2ecore map. This
>> generates an extra file, if you open that file then you can see the
>> relation between the ecore model elements and their corresponding xsd
>> element. This could give more info.
>>
>> gr. Martin
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>>
>>> This time I deleted the User and Group interface and classes. When I
>>> generated it did indeed add the getUserGroup and getGroupUser methods
>>> where expected.
>>>
>>> The thing I did not expect was that the the Group.getUser() and
>>> User.getGroup(), both returning a single object. I can just ignore
>>> these but it is a little confusing to have them there.
>>>
>>> regards,
>>>
>>> David
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> I would expect that there is a method getGroupUser in Group
>>>> returning an EList<User> and a getUserGroup in User which returns an
>>>> EList<Group>.
>>>> Did you reload the xsd in the genmodel and then regenerate the model
>>>> code?
>>>>
>>>> gr. Martin
>>>>
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> The suggestions you gave did generate the correct database tables.
>>>>> But I am confused, as the generate methods do not reflect the
>>>>> underlying tables. For example I have
>>>>>
>>>>> <xsd:complexType name="Group">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="user")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> ....
>>>>>
>>>>>
>>>>> <xsd:complexType name="User">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="group")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> ....
>>>>>
>>>>>
>>>>> This generates the following hibernate.hbm.xml
>>>>>
>>>>> Inside Group entity declaration we have
>>>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="User" unique="true"
>>>>> foreign-key="group_groupuser">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>>
>>>>> Inside User declaration we have
>>>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="Group" unique="true"
>>>>> foreign-key="user_usergroup">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>> But the generated User Interface has a method "Group getGroup();"
>>>>> The generated Group Interface has "User getUser();"
>>>>>
>>>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>>>> getUser();" shouldn't it?
>>>>>
>>>>> Thx.
>>>>>
>>>>> David
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi David,
>>>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>>>> userrole is present as a separate type) case anymore are we?
>>>>>>
>>>>>> To get the result of what you want with hibernate add this
>>>>>> annotation in the efeature which is the list:
>>>>>> @OneToMany(indexed=false, mappedBy="one")
>>>>>> @JoinTable(name="maniesofone")
>>>>>>
>>>>>> where one is the opposite feature name.
>>>>>>
>>>>>> Some other info:
>>>>>> Teneo as a default maps non-containment associations with a
>>>>>> jointable (is controlled by the option:
>>>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>>>> However, for bidirectional lists the many-to-one mapping creates
>>>>>> an additional foreign key on the many side. This because hibernate
>>>>>> does not support bidirectional lists. To prevent this you should
>>>>>> also disable the mapping of the list index (see the map as bag and
>>>>>> map as idbag in the other replies, or used indexed="false").
>>>>>>
>>>>>> So to summarize you can try to set the option
>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see
>>>>>> where join tables are created.
>>>>>>
>>>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>>>> is not strictly required because the many is always only used once
>>>>>> (as the relation is bidirectional).
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>>
>>>>>> David Wynter wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> After reading the Hibernate manual a little I found this example
>>>>>>> for one to many, many to one
>>>>>>>
>>>>>>> <class name="Person">
>>>>>>> <id name="id" column="personId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <set name="addresses"
>>>>>>> table="PersonAddress">
>>>>>>> <key column="personId"/>
>>>>>>> <many-to-many column="addressId"
>>>>>>> unique="true"
>>>>>>> class="Address"/>
>>>>>>> </set>
>>>>>>> </class>
>>>>>>>
>>>>>>> <class name="Address">
>>>>>>> <id name="id" column="addressId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <join table="PersonAddress"
>>>>>>> inverse="true"
>>>>>>> optional="true">
>>>>>>> <key column="addressId"/>
>>>>>>> <many-to-one name="person"
>>>>>>> column="personId"
>>>>>>> not-null="true"/>
>>>>>>> </join>
>>>>>>> </class>
>>>>>>>
>>>>>>> What annotation would we use to achieve this configuration?
>>>>>>>
>>>>>>> Thx.
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> Hi David,
>>>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>>>
>>>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>>>> technically the reference from user to userrole and from role to
>>>>>>>> userrole are not manytomany but onetomany. Because you
>>>>>>>> explicitly say that is a manytomany you get three tables:
>>>>>>>> for the join between user and userrole
>>>>>>>> for userrole itself
>>>>>>>> for the join from role to userrole.
>>>>>>>>
>>>>>>>> In case you had not explicitly modelled the join type then a
>>>>>>>> manytomany is appropriate.
>>>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>>>
>>>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>>>> Normally this is computed by Teneo.
>>>>>>>>
>>>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>>>> you don't need the index on any of the associations then you can
>>>>>>>> also
>>>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>>>> idbag is used), or
>>>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>>>> hibernate bag is used.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> David Wynter wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> In which case the example on ManyToMany on
>>>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>>>
>>>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>>>> liking.
>>>>>>>>>
>>>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>>>
>>>>>>>>> What I get is 3 tables:
>>>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>>>> userole with columns - e_id, user, userrole
>>>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>>>
>>>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>>>> do these 3 tables give over a single table? If I have lot of
>>>>>>>>> many to many my schema will be much larger and much more
>>>>>>>>> difficult for people to understand.
>>>>>>>>>
>>>>>>>>> Thx,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Martin Taal wrote:
>>>>>>>>>> Hi David,
>>>>>>>>>> I think there should be a comma between MERGE and PERSIST in
>>>>>>>>>> the cascade attribute.
>>>>>>>>>>
>>>>>>>>>> gr. Martin
>>>>>>>>>>
>>>>>>>>>> David Wynter wrote:
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>>>> Ended up with this
>>>>>>>>>>>
>>>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>>>> <xsd:schema
>>>>>>>>>>> xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>>>> attributeFormDefault="unqualified"
>>>>>>>>>>> elementFormDefault="qualified"
>>>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>>>> </xsd:restriction>
>>>>>>>>>>> </xsd:simpleType>
>>>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:documentation>
>>>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly'
>>>>>>>>>>> and 'CrudUser'</xsd:p>
>>>>>>>>>>> </xsd:documentation>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="user">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="role">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="name"
>>>>>>>>>>> type="xsd:string"></xsd:attribute>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>>>> <xsd:sequence>
>>>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="Role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> </xsd:schema>
>>>>>>>>>>>
>>>>>>>>>>> This gives me the exception:
>>>>>>>>>>>
>>>>>>>>>>> Exception in thread "main"
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>>>> character, Comma (,).
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>>>> structure to the example.
>>>>>>>>>>>
>>>>>>>>>>> Thx.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org]]>Martin Taal2008-09-30T08:57:49-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423412/#msg_423412
I added the option to create the xsd2ecore map. Here are the relevant
parts. I cannot see what there is in this that suggests that the Group
getGroup() would be generated on the User interface.
The ecore User does have an eFeature for the Group as well as one for
the userGroup. The ecore Group does have an efeature for the User and
the valid one for the groupUser.
Changing the sequence to minOccurs and maxOccurs = 1 makes no difference
in the outcome.
Thx.
David
Martin Taal wrote:
> Hi David,
> Normally EMF should regenerate the code without the need to delete the
> classes/interfaces. Also I can't really imagine that the getUser or
> getGroup originate from the two multi-occurence element you showed below.
> Maybe because there is a sequence with minOccurs="0" that you get these,
> but I can't really understand why. (maybe Ed knows)
>
> You can also check the ecore to see if Group has a user efeature (and
> User a group efeature). Then when importing the xsd in the genmodel I
> think you can specify somewhere to generate a xsd2ecore map. This
> generates an extra file, if you open that file then you can see the
> relation between the ecore model elements and their corresponding xsd
> element. This could give more info.
>
> gr. Martin
>
> David Wynter wrote:
>> Hi,
>>
>>
>> This time I deleted the User and Group interface and classes. When I
>> generated it did indeed add the getUserGroup and getGroupUser methods
>> where expected.
>>
>> The thing I did not expect was that the the Group.getUser() and
>> User.getGroup(), both returning a single object. I can just ignore
>> these but it is a little confusing to have them there.
>>
>> regards,
>>
>> David
>>
>> Martin Taal wrote:
>>> Hi David,
>>> I would expect that there is a method getGroupUser in Group returning
>>> an EList<User> and a getUserGroup in User which returns an EList<Group>.
>>> Did you reload the xsd in the genmodel and then regenerate the model
>>> code?
>>>
>>> gr. Martin
>>>
>>>
>>> David Wynter wrote:
>>>> Hi,
>>>>
>>>> The suggestions you gave did generate the correct database tables.
>>>> But I am confused, as the generate methods do not reflect the
>>>> underlying tables. For example I have
>>>>
>>>> <xsd:complexType name="Group">
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>>>> mappedBy="user") @JoinTable(name="UserGroup")</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> </xsd:sequence>
>>>> ....
>>>>
>>>>
>>>> <xsd:complexType name="User">
>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>>> <xsd:annotation>
>>>> <xsd:appinfo source="teneo.jpa"> @OneToMany(indexed=false,
>>>> mappedBy="group") @JoinTable(name="UserGroup")</xsd:appinfo>
>>>> </xsd:annotation>
>>>> </xsd:element>
>>>> ....
>>>>
>>>>
>>>> This generates the following hibernate.hbm.xml
>>>>
>>>> Inside Group entity declaration we have
>>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>>> lazy="true" cascade="all,delete-orphan">
>>>> <key update="true">
>>>> <column name="`group_id`" not-null="true"
>>>> unique="false"/>
>>>> </key>
>>>> <many-to-many entity-name="User" unique="true"
>>>> foreign-key="group_groupuser">
>>>> <column name="`user_id`" not-null="true"
>>>> unique="false"/>
>>>> </many-to-many>
>>>> </bag>
>>>>
>>>>
>>>> Inside User declaration we have
>>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>>> lazy="true" cascade="all,delete-orphan">
>>>> <key update="true">
>>>> <column name="`user_id`" not-null="true"
>>>> unique="false"/>
>>>> </key>
>>>> <many-to-many entity-name="Group" unique="true"
>>>> foreign-key="user_usergroup">
>>>> <column name="`group_id`" not-null="true"
>>>> unique="false"/>
>>>> </many-to-many>
>>>> </bag>
>>>>
>>>> But the generated User Interface has a method "Group getGroup();"
>>>> The generated Group Interface has "User getUser();"
>>>>
>>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>>> getUser();" shouldn't it?
>>>>
>>>> Thx.
>>>>
>>>> David
>>>>
>>>> Martin Taal wrote:
>>>>> Hi David,
>>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>>> userrole is present as a separate type) case anymore are we?
>>>>>
>>>>> To get the result of what you want with hibernate add this
>>>>> annotation in the efeature which is the list:
>>>>> @OneToMany(indexed=false, mappedBy="one")
>>>>> @JoinTable(name="maniesofone")
>>>>>
>>>>> where one is the opposite feature name.
>>>>>
>>>>> Some other info:
>>>>> Teneo as a default maps non-containment associations with a
>>>>> jointable (is controlled by the option:
>>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>>> However, for bidirectional lists the many-to-one mapping creates an
>>>>> additional foreign key on the many side. This because hibernate
>>>>> does not support bidirectional lists. To prevent this you should
>>>>> also disable the mapping of the list index (see the map as bag and
>>>>> map as idbag in the other replies, or used indexed="false").
>>>>>
>>>>> So to summarize you can try to set the option
>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see
>>>>> where join tables are created.
>>>>>
>>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>>> is not strictly required because the many is always only used once
>>>>> (as the relation is bidirectional).
>>>>>
>>>>> gr. Martin
>>>>>
>>>>>
>>>>> David Wynter wrote:
>>>>>> Hi,
>>>>>>
>>>>>> After reading the Hibernate manual a little I found this example
>>>>>> for one to many, many to one
>>>>>>
>>>>>> <class name="Person">
>>>>>> <id name="id" column="personId">
>>>>>> <generator class="native"/>
>>>>>> </id>
>>>>>> <set name="addresses"
>>>>>> table="PersonAddress">
>>>>>> <key column="personId"/>
>>>>>> <many-to-many column="addressId"
>>>>>> unique="true"
>>>>>> class="Address"/>
>>>>>> </set>
>>>>>> </class>
>>>>>>
>>>>>> <class name="Address">
>>>>>> <id name="id" column="addressId">
>>>>>> <generator class="native"/>
>>>>>> </id>
>>>>>> <join table="PersonAddress"
>>>>>> inverse="true"
>>>>>> optional="true">
>>>>>> <key column="addressId"/>
>>>>>> <many-to-one name="person"
>>>>>> column="personId"
>>>>>> not-null="true"/>
>>>>>> </join>
>>>>>> </class>
>>>>>>
>>>>>> What annotation would we use to achieve this configuration?
>>>>>>
>>>>>> Thx.
>>>>>>
>>>>>> David
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> Hi David,
>>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>>
>>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>>> technically the reference from user to userrole and from role to
>>>>>>> userrole are not manytomany but onetomany. Because you explicitly
>>>>>>> say that is a manytomany you get three tables:
>>>>>>> for the join between user and userrole
>>>>>>> for userrole itself
>>>>>>> for the join from role to userrole.
>>>>>>>
>>>>>>> In case you had not explicitly modelled the join type then a
>>>>>>> manytomany is appropriate.
>>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>>
>>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>>> Normally this is computed by Teneo.
>>>>>>>
>>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>>> you don't need the index on any of the associations then you can
>>>>>>> also
>>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>>> idbag is used), or
>>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>>> hibernate bag is used.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> David Wynter wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> In which case the example on ManyToMany on
>>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>>
>>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>>> liking.
>>>>>>>>
>>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>>
>>>>>>>> What I get is 3 tables:
>>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>>> userole with columns - e_id, user, userrole
>>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>>
>>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>>> do these 3 tables give over a single table? If I have lot of
>>>>>>>> many to many my schema will be much larger and much more
>>>>>>>> difficult for people to understand.
>>>>>>>>
>>>>>>>> Thx,
>>>>>>>>
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>>
>>>>>>>> Martin Taal wrote:
>>>>>>>>> Hi David,
>>>>>>>>> I think there should be a comma between MERGE and PERSIST in
>>>>>>>>> the cascade attribute.
>>>>>>>>>
>>>>>>>>> gr. Martin
>>>>>>>>>
>>>>>>>>> David Wynter wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>>> Ended up with this
>>>>>>>>>>
>>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>>> <xsd:schema
>>>>>>>>>> xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>>> attributeFormDefault="unqualified" elementFormDefault="qualified"
>>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>>> </xsd:restriction>
>>>>>>>>>> </xsd:simpleType>
>>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:documentation>
>>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly' and
>>>>>>>>>> 'CrudUser'</xsd:p>
>>>>>>>>>> </xsd:documentation>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="user">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:attribute>
>>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>>> </xsd:element>
>>>>>>>>>>
>>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>>
>>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="role">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:attribute>
>>>>>>>>>> <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>
>>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>>> <xsd:sequence>
>>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>> <xsd:annotation>
>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>> targetEntity="Role")
>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>> </xsd:annotation>
>>>>>>>>>> </xsd:element>
>>>>>>>>>> </xsd:sequence>
>>>>>>>>>> </xsd:complexType>
>>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>>
>>>>>>>>>> </xsd:schema>
>>>>>>>>>>
>>>>>>>>>> This gives me the exception:
>>>>>>>>>>
>>>>>>>>>> Exception in thread "main"
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>>> character, Comma (,).
>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>>
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>>
>>>>>>>>>> at
>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>>> structure to the example.
>>>>>>>>>>
>>>>>>>>>> Thx.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>]]>David Wynter2008-09-30T08:59:22-00:00Re: [Teneo] Exception using ManyToMany annotation
https://www.eclipse.org/forums/index.php/mv/msg/134986/423419/#msg_423419
Had not refreshed my newsgroup reader and missed the reply. Thanks it
works, am now in eCore nirvana, I can achieve both the db schema and the
generated source code I need to achieve my ends.
Regards,
David
David
Ed Merks wrote:
> Martin,
>
> Comments below.
>
>
> Martin Taal wrote:
>> Hi David,
>> Normally EMF should regenerate the code without the need to delete the
>> classes/interfaces. Also I can't really imagine that the getUser or
>> getGroup originate from the two multi-occurence element you showed below.
> They originate from the "ecore:opposite" annotations. The opposite of a
> containment feature is a container feature and you can have at most one
> container.
>> Maybe because there is a sequence with minOccurs="0" that you get
>> these, but I can't really understand why. (maybe Ed knows)
>>
>> You can also check the ecore to see if Group has a user efeature (and
>> User a group efeature). Then when importing the xsd in the genmodel I
>> think you can specify somewhere to generate a xsd2ecore map. This
>> generates an extra file, if you open that file then you can see the
>> relation between the ecore model elements and their corresponding xsd
>> element. This could give more info.
>>
>> gr. Martin
>>
>> David Wynter wrote:
>>> Hi,
>>>
>>>
>>> This time I deleted the User and Group interface and classes. When I
>>> generated it did indeed add the getUserGroup and getGroupUser methods
>>> where expected.
>>>
>>> The thing I did not expect was that the the Group.getUser() and
>>> User.getGroup(), both returning a single object. I can just ignore
>>> these but it is a little confusing to have them there.
>>>
>>> regards,
>>>
>>> David
>>>
>>> Martin Taal wrote:
>>>> Hi David,
>>>> I would expect that there is a method getGroupUser in Group
>>>> returning an EList<User> and a getUserGroup in User which returns an
>>>> EList<Group>.
>>>> Did you reload the xsd in the genmodel and then regenerate the model
>>>> code?
>>>>
>>>> gr. Martin
>>>>
>>>>
>>>> David Wynter wrote:
>>>>> Hi,
>>>>>
>>>>> The suggestions you gave did generate the correct database tables.
>>>>> But I am confused, as the generate methods do not reflect the
>>>>> underlying tables. For example I have
>>>>>
>>>>> <xsd:complexType name="Group">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="groupUser" type="secmsec:User" ecore:opposite="group">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="user")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> </xsd:sequence>
>>>>> ....
>>>>>
>>>>>
>>>>> <xsd:complexType name="User">
>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>> <xsd:element minOccurs="0" maxOccurs="unbounded"
>>>>> name="userGroup" type="secmsec:Group" ecore:opposite="user">
>>>>> <xsd:annotation>
>>>>> <xsd:appinfo source="teneo.jpa">
>>>>> @OneToMany(indexed=false, mappedBy="group")
>>>>> @JoinTable(name="UserGroup")</xsd:appinfo>
>>>>> </xsd:annotation>
>>>>> </xsd:element>
>>>>> ....
>>>>>
>>>>>
>>>>> This generates the following hibernate.hbm.xml
>>>>>
>>>>> Inside Group entity declaration we have
>>>>> <bag name="groupUser" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="User" unique="true"
>>>>> foreign-key="group_groupuser">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>>
>>>>> Inside User declaration we have
>>>>> <bag name="userGroup" inverse="true" table="`usergroup`"
>>>>> lazy="true" cascade="all,delete-orphan">
>>>>> <key update="true">
>>>>> <column name="`user_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </key>
>>>>> <many-to-many entity-name="Group" unique="true"
>>>>> foreign-key="user_usergroup">
>>>>> <column name="`group_id`" not-null="true"
>>>>> unique="false"/>
>>>>> </many-to-many>
>>>>> </bag>
>>>>>
>>>>> But the generated User Interface has a method "Group getGroup();"
>>>>> The generated Group Interface has "User getUser();"
>>>>>
>>>>> This should be "EList<Group> getGroup();" and "Elist<User>
>>>>> getUser();" shouldn't it?
>>>>>
>>>>> Thx.
>>>>>
>>>>> David
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi David,
>>>>>> To be sure we are not discussing the User, UserRole, Role (whereby
>>>>>> userrole is present as a separate type) case anymore are we?
>>>>>>
>>>>>> To get the result of what you want with hibernate add this
>>>>>> annotation in the efeature which is the list:
>>>>>> @OneToMany(indexed=false, mappedBy="one")
>>>>>> @JoinTable(name="maniesofone")
>>>>>>
>>>>>> where one is the opposite feature name.
>>>>>>
>>>>>> Some other info:
>>>>>> Teneo as a default maps non-containment associations with a
>>>>>> jointable (is controlled by the option:
>>>>>> PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS ).
>>>>>> However, for bidirectional lists the many-to-one mapping creates
>>>>>> an additional foreign key on the many side. This because hibernate
>>>>>> does not support bidirectional lists. To prevent this you should
>>>>>> also disable the mapping of the list index (see the map as bag and
>>>>>> map as idbag in the other replies, or used indexed="false").
>>>>>>
>>>>>> So to summarize you can try to set the option
>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true and then see
>>>>>> where join tables are created.
>>>>>>
>>>>>> Note that for a bidirectional one-to-many/many-to-one a join table
>>>>>> is not strictly required because the many is always only used once
>>>>>> (as the relation is bidirectional).
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>>
>>>>>> David Wynter wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> After reading the Hibernate manual a little I found this example
>>>>>>> for one to many, many to one
>>>>>>>
>>>>>>> <class name="Person">
>>>>>>> <id name="id" column="personId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <set name="addresses"
>>>>>>> table="PersonAddress">
>>>>>>> <key column="personId"/>
>>>>>>> <many-to-many column="addressId"
>>>>>>> unique="true"
>>>>>>> class="Address"/>
>>>>>>> </set>
>>>>>>> </class>
>>>>>>>
>>>>>>> <class name="Address">
>>>>>>> <id name="id" column="addressId">
>>>>>>> <generator class="native"/>
>>>>>>> </id>
>>>>>>> <join table="PersonAddress"
>>>>>>> inverse="true"
>>>>>>> optional="true">
>>>>>>> <key column="addressId"/>
>>>>>>> <many-to-one name="person"
>>>>>>> column="personId"
>>>>>>> not-null="true"/>
>>>>>>> </join>
>>>>>>> </class>
>>>>>>>
>>>>>>> What annotation would we use to achieve this configuration?
>>>>>>>
>>>>>>> Thx.
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> Hi David,
>>>>>>>> Thanks for pointing that out, I have repaired that.
>>>>>>>>
>>>>>>>> In your case afaics you have an explicit join type UserRole. So
>>>>>>>> technically the reference from user to userrole and from role to
>>>>>>>> userrole are not manytomany but onetomany. Because you
>>>>>>>> explicitly say that is a manytomany you get three tables:
>>>>>>>> for the join between user and userrole
>>>>>>>> for userrole itself
>>>>>>>> for the join from role to userrole.
>>>>>>>>
>>>>>>>> In case you had not explicitly modelled the join type then a
>>>>>>>> manytomany is appropriate.
>>>>>>>> Changing the annotation to OneToMany will solve this for you.
>>>>>>>>
>>>>>>>> The targetentity is not required in the manytomany/onetomany.
>>>>>>>> Normally this is computed by Teneo.
>>>>>>>>
>>>>>>>> Also I noticed that you had indexed="false" only on one side. If
>>>>>>>> you don't need the index on any of the associations then you can
>>>>>>>> also
>>>>>>>> PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to true (then always a
>>>>>>>> idbag is used), or
>>>>>>>> PersistenceOptions.ALWAYS_MAP_LIST_AS_BAG to true then always a
>>>>>>>> hibernate bag is used.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> David Wynter wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> In which case the example on ManyToMany on
>>>>>>>>> http://www.elver.org/hibernate/ejb3_examples.html is wrong.
>>>>>>>>>
>>>>>>>>> Now that it generates it generates way too many tables for my
>>>>>>>>> liking.
>>>>>>>>>
>>>>>>>>> I know to represent User >-< Role (many to many) I need one
>>>>>>>>> table, lets call it UserRole, it has 2 columns, user_id and
>>>>>>>>> role_id. user_id joins to User.id and role_id joins to Role.id
>>>>>>>>>
>>>>>>>>> What I get is 3 tables:
>>>>>>>>> userrole_role with columns - userrole, role userrole_idx
>>>>>>>>> userole with columns - e_id, user, userrole
>>>>>>>>> role_userrole with columns - role, userole, role_userole_idx
>>>>>>>>>
>>>>>>>>> Is there a way to end up with a simpler schema? What advantages
>>>>>>>>> do these 3 tables give over a single table? If I have lot of
>>>>>>>>> many to many my schema will be much larger and much more
>>>>>>>>> difficult for people to understand.
>>>>>>>>>
>>>>>>>>> Thx,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Martin Taal wrote:
>>>>>>>>>> Hi David,
>>>>>>>>>> I think there should be a comma between MERGE and PERSIST in
>>>>>>>>>> the cascade attribute.
>>>>>>>>>>
>>>>>>>>>> gr. Martin
>>>>>>>>>>
>>>>>>>>>> David Wynter wrote:
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> I followed the ejb3_example on the many to many annotations.
>>>>>>>>>>> Ended up with this
>>>>>>>>>>>
>>>>>>>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>>>>>>>> <xsd:schema
>>>>>>>>>>> xmlns:secmsec="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
>>>>>>>>>>> xmlns:xlink="http://www.w3.org/1999/xlink"
>>>>>>>>>>> attributeFormDefault="unqualified"
>>>>>>>>>>> elementFormDefault="qualified"
>>>>>>>>>>> targetNamespace="http://www.stpware.com/secmsecurity"
>>>>>>>>>>> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>>>>>>>>>> <xsd:import schemaLocation="xml.xsd"
>>>>>>>>>>> namespace="http://www.w3.org/XML/1998/namespace" />
>>>>>>>>>>> <xsd:simpleType name="javaDate"
>>>>>>>>>>> ecore:instanceClass="java.util.Date">
>>>>>>>>>>> <xsd:restriction base="xsd:dateTime">
>>>>>>>>>>> </xsd:restriction>
>>>>>>>>>>> </xsd:simpleType>
>>>>>>>>>>> <xsd:complexType name="User">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:documentation>
>>>>>>>>>>> <xsd:p>The basic user entity. Kept simple, the Role
>>>>>>>>>>> attribute is just a string. 'Admin', 'Cleanse', 'ReadOnly'
>>>>>>>>>>> and 'CrudUser'</xsd:p>
>>>>>>>>>>> </xsd:documentation>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="user">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="user" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="firstName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="surname" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="email" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="salutation" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="loginName" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="password" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="phone" type="xsd:string" />
>>>>>>>>>>> <xsd:attribute name="lastLogin" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userStart" type="secmsec:javaDate" />
>>>>>>>>>>> <xsd:attribute name="userEnd" type="secmsec:javaDate" />
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="user" type="secmsec:User">
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:element name="role" type="secmsec:Role"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="Role">
>>>>>>>>>>> <xsd:sequence minOccurs="0" maxOccurs="1">
>>>>>>>>>>> <xsd:element name="userrole" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:UserRole" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="role">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> <xsd:attribute name="id" type="xsd:int">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">@Id
>>>>>>>>>>> @GeneratedValue(strategy=IDENTITY)</xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:attribute>
>>>>>>>>>>> <xsd:attribute name="name"
>>>>>>>>>>> type="xsd:string"></xsd:attribute>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>>
>>>>>>>>>>> <xsd:complexType name="UserRole">
>>>>>>>>>>> <xsd:sequence>
>>>>>>>>>>> <xsd:element name="user" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:User" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="User" indexed="false")
>>>>>>>>>>> @JoinTable(name="UserRole")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> <xsd:element name="role" type="xsd:IDREF"
>>>>>>>>>>> ecore:reference="secmsec:Role" maxOccurs="unbounded"
>>>>>>>>>>> ecore:opposite="userrole">
>>>>>>>>>>> <xsd:annotation>
>>>>>>>>>>> <xsd:appinfo source="teneo.jpa">
>>>>>>>>>>> @ManyToMany(fetch=EAGER cascade={MERGE PERSIST}
>>>>>>>>>>> targetEntity="Role")
>>>>>>>>>>> </xsd:appinfo>
>>>>>>>>>>> </xsd:annotation>
>>>>>>>>>>> </xsd:element>
>>>>>>>>>>> </xsd:sequence>
>>>>>>>>>>> </xsd:complexType>
>>>>>>>>>>> <xsd:element name="userrole"
>>>>>>>>>>> type="secmsec:UserRole"></xsd:element>
>>>>>>>>>>>
>>>>>>>>>>> </xsd:schema>
>>>>>>>>>>>
>>>>>>>>>>> This gives me the exception:
>>>>>>>>>>>
>>>>>>>>>>> Exception in thread "main"
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParserExc eption:
>>>>>>>>>>> Found Attribute Name but expected one of : Array End (}), =
>>>>>>>>>>> character, Comma (,).
>>>>>>>>>>> @ManyToMany(fetch=LAZY cascade={MERGE PERSIST_}
>>>>>>>>>>> targetEntity="UserRole" mappedBy="role")
>>>>>>>>>>> Current lexeme: PERSIST
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.ch eckToken(AnnotationParser.java:261)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseArray(AnnotationParser.java:217)
>>>>>>>>>>>
>>>>>>>>>>> at
>>>>>>>>>>> org.eclipse.emf.teneo.annotations.parser.AnnotationParser.pa rseContent(AnnotationParser.java:181)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> It is very explicit, but I cannot see what is different in
>>>>>>>>>>> structure to the example.
>>>>>>>>>>>
>>>>>>>>>>> Thx.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>]]>David Wynter2008-09-30T09:38:07-00:00