Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [Teneo] Exception using ManyToMany annotation
[Teneo] Exception using ManyToMany annotation [message #423287] Fri, 26 September 2008 10:34 Go to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423288 is a reply to message #423287] Fri, 26 September 2008 10:35 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423289 is a reply to message #423288] Fri, 26 September 2008 10:58 Go to previous messageGo to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
>
>
Re: [Teneo] Exception using ManyToMany annotation [message #423290 is a reply to message #423289] Fri, 26 September 2008 11:29 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423301 is a reply to message #423290] Fri, 26 September 2008 16:15 Go to previous messageGo to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
>>>
>>>
>
>
Re: [Teneo] Exception using ManyToMany annotation [message #423305 is a reply to message #423301] Fri, 26 September 2008 17:22 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423379 is a reply to message #423305] Mon, 29 September 2008 16:21 Go to previous messageGo to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
>>>>>
>>>>>
>>>
>>>
>
>
Re: [Teneo] Exception using ManyToMany annotation [message #423386 is a reply to message #423379] Mon, 29 September 2008 17:14 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423387 is a reply to message #423386] Mon, 29 September 2008 18:06 Go to previous messageGo to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>
Re: [Teneo] Exception using ManyToMany annotation [message #423388 is a reply to message #423387] Mon, 29 September 2008 18:29 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
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
Re: [Teneo] Exception using ManyToMany annotation [message #423390 is a reply to message #423388] Mon, 29 September 2008 19:03 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
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
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: [Teneo] Exception using ManyToMany annotation [message #423392 is a reply to message #423390] Mon, 29 September 2008 19:21 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Ed,
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
Re: [Teneo] Exception using ManyToMany annotation [message #423412 is a reply to message #423388] Tue, 30 September 2008 08:59 Go to previous messageGo to next message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
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
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>
Re: [Teneo] Exception using ManyToMany annotation [message #423413 is a reply to message #423412] Tue, 30 September 2008 08:57 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Hi David,
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
Re: [Teneo] Exception using ManyToMany annotation [message #423419 is a reply to message #423390] Tue, 30 September 2008 09:38 Go to previous message
David Wynter is currently offline David WynterFriend
Messages: 4624
Registered: July 2009
Senior Member
Hi,

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
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
Previous Topic:Manual Notificatios
Next Topic:CDO: Reflective Feature Delegation required - but how to invoke not generated code?
Goto Forum:
  


Current Time: Thu Mar 28 16:37:14 GMT 2024

Powered by FUDForum. Page generated in 0.04745 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top