You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Uden <ud...@gmail.com> on 2008/05/08 12:17:03 UTC
Re: Question about @OneToMany
The solution quoted below but has a consequence for the Java class model: the
OneToMany relationship becomes bi-directional instead of uni-directional.
What is the reason for creating the join-table?
I thought (based on my database experience) that a join-table is only
required for ManyToMany relationships.
If you look at the data in the join-table of a uni-directional relation (no
mappedBy attribute), the relation between the join-table and master table is
always OneToOne, so this relation could be handled by a FK-field in the
detail-table.
thanks for your explanation,
Uden
Andy Schlaikjer-2 wrote:
>
> Marco Schwarz wrote:
>>
>> How can I make only 2 tables?
>
> Here's my guess:
>
> First, use the "mappedBy" property of the @OneToMany annotation, like
> this:
>
> @Entity
> class ModelObject {
> ...
>
> @ManyToOne
> ModelObject parent;
>
> @OneToMany(mappedBy="parent")
> List<ModelObject> children;
>
> ...
> }
>
> This way, an extra join table won't be necessary to encode the parent
> child relationship. Only the "parent_id" column in the "ModelObject"
> table will be used to encode the relationship.
>
--
View this message in context: http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17124365.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Question about @OneToMany
Posted by Andy Schlaikjer <ha...@cs.cmu.edu>.
I think I may have found OpenJPA's solution to this problem. Could
someone comment? Thanks!
http://openjpa.apache.org/docs/latest/manual/manual.html#ref_guide_mapping_jpa_onemany
@Entity
public class Node
{
@Id
protected long id;
@OneToMany
@ElementJoinColumn(name="parent_id", target="id")
protected Collection<Node> children;
}
Andy Schlaikjer wrote:
> I think it's not wonderful that you have to add an extra field to your
> object model if you're really not interested in modeling the ManyToOne
> side of a relationship like this. However, at the moment you can't
> "reuse" a single table to map both an entity and a join table, so we're
> stuck.
>
> For example, this doesn't work:
>
> @Entity
> public class Node
> {
> @Id
> protected long id;
>
> @OneToMany()
> @JoinTable(
> name = "Node",
> joinColumns = @JoinColumn(name = "parent_id"), // i wish
> inverseJoinColumns = @JoinColumn(name = "id")
> )
> protected Collection<Node> children;
>
> ...
> }
>
> Michael Vorburger wrote:
>> Hello,
>>
>> Similar situation here, and I wonder about people's thoughts & pros/cons
>> regarding this:
>>
>>> Your solution (anotate "ModelObject parent;" with @ManyToOne instead
>> of @Transient and add mappedBy="parent" to @OneToMany) works, also for
>> my application, but turns the uni-directional relation into a
>> bi-directional relation. And this bi-directional relation is more
>> dificult to manage and not needed in our Java application.
>>
>> Why is this "bi-directional relation is more dificult to manage and not
>> needed in our Java application" ? If you let OpenJPA deal with this for
>> you with the Managed Inverses
>> (http://openjpa.apache.org/docs/latest/manual/ref_guide_inverses.html),
>> what's the problem with an additional field? Hide it even - if for some
>> reason you don't want to expose the bi-directionality to the users of
>> the object model for keep that '@ManyToOne ModelObject parent' as a
>> private with no setters and getters - just to get the desired mapping!
>>
>> What's the issue with this approach? (Portability and not wanting to
>> use Managed Inverses aside; but I don't know if that's strong enough,
>> you're using OpenJPA specific configuration elsewhere already, and
>> that's really what this is - a runtime configuration specific to one JPA
>> implementation. Other implementations may have a similar feature? If
>> not, worst case, when switching, manually code the logic [with loop
>> detection, if needed]).
>>
>> Regards,
>> Michael
>>
>>
>> -----Original Message-----
>> From: Uden [mailto:udenvh@gmail.com] Sent: jeudi, 8. mai 2008 21:37
>> To: users@openjpa.apache.org
>> Subject: Re: Question about @OneToMany
>>
>>
>> Hi Andy, thanks for the quick response.
>>
>> In my application i had three tables generated (a master, a detail and a
>> join table) for what i believed could be modelled by just the master and
>> a detail table (at least in traditional database modeling). So when i
>> was looking for a solution to simplify my datamodel in the database, i
>> found this posting which looked similar to my problem and added my
>> question.
>>
>> I need to map the following Java classes (note i reuse Marco's code
>> example):
>>
>> @MappedSuperclass
>> @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
>> class ModelObject {
>>
>> @Id
>> private int id
>>
>> @Transient
>> ModelObject parent;
>>
>> @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
>> List<ModelObject> children;
>>
>> .....
>> }
>>
>> @Entity
>> class Company extends ModelObject {
>> }
>>
>> @Entity
>> class Employer extends ModelObject {
>> }
>>
>> to the folowing database tables:
>>
>> COMPANY (ID (PK)
>> , ...
>> )
>>
>> and EMPLOYEE
>> (ID (PK)
>> ,COMPANY_ID (FK to COMPANY.ID)
>> , ...
>> )
>>
>> In Marco's original question he indicates that in his case "openjpa
>> create 4 tables (Company, Company_children, Emplpyer and
>> Employer_children).". Your solution (anotate "ModelObject parent;"
>> with @ManyToOne instead of
>> @Transient and add mappedBy="parent" to @OneToMany) works, also for my
>> application, but turns the uni-directional relation into a
>> bi-directional relation. And this bi-directional relation is more
>> dificult to manage and not
>> needed in our Java application. It does however results in a simpler
>> datamodel.
>> Your second solution changes the direction (or ownership) of the
>> relation in the Java model.
>>
>> So it seems we have to trade a simplified database datamodel versus a
>> simplified Java datamodel.
>>
>> Or is there an other solution?
>>
>> thanks,
>> Uden
>>
>>
>> hazen wrote:
>>> Hi Uden,
>>>
>>> If you'd rather keep the relation unidirectional just remove the
>>> `children` field-- the `parent` field alone is enough to encode the
>>> relation without recourse to a separate join table. Either way, I
>>> don't see how the quoted section below results in a join table. Both
>>> fields rely solely on a "parent_id" column within the "ModelObject"
>>> table, not on some other join table. Am I missing something?
>>>
>>> Andy
>>>
>>> Uden wrote:
>>>> The solution quoted below but has a consequence for the Java class
>> model:
>>>> the
>>>> OneToMany relationship becomes bi-directional instead of
>> uni-directional.
>>>> What is the reason for creating the join-table?
>>>> I thought (based on my database experience) that a join-table is only
>>
>>>> required for ManyToMany relationships.
>>>> If you look at the data in the join-table of a uni-directional
>>>> relation (no mappedBy attribute), the relation between the join-table
>>
>>>> and master table is always OneToOne, so this relation could be
>>>> handled by a FK-field in the detail-table.
>>>>
>>>> thanks for your explanation,
>>>> Uden
>>>>
>>>>
>>>> Andy Schlaikjer-2 wrote:
>>>>> Marco Schwarz wrote:
>>>>>> How can I make only 2 tables?
>>>>> Here's my guess:
>>>>>
>>>>> First, use the "mappedBy" property of the @OneToMany annotation, like
>>>>> this:
>>>>>
>>>>> @Entity
>>>>> class ModelObject {
>>>>> ...
>>>>>
>>>>> @ManyToOne
>>>>> ModelObject parent;
>>>>>
>>>>> @OneToMany(mappedBy="parent")
>>>>> List<ModelObject> children;
>>>>>
>>>>> ...
>>>>> }
>>>>>
>>>>> This way, an extra join table won't be necessary to encode the
>>>>> parent child relationship. Only the "parent_id" column in the
>> "ModelObject"
>>>>> table will be used to encode the relationship.
>>>>>
>>>
>>
>> --
>> View this message in context:
>> http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17134828.ht
>> ml
>> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>>
>>
>> ____________________________________________________________
>>
>> • This email and any files transmitted with it are CONFIDENTIAL and
>> intended
>> solely for the use of the individual or entity to which they are
>> addressed.
>> • Any unauthorized copying, disclosure, or distribution of the
>> material within
>> this email is strictly forbidden.
>> • Any views or opinions presented within this e-mail are solely those
>> of the
>> author and do not necessarily represent those of Odyssey Financial
>> Technologies SA unless otherwise specifically stated.
>> • An electronic message is not binding on its sender. Any message
>> referring to
>> a binding engagement must be confirmed in writing and duly signed.
>> • If you have received this email in error, please notify the sender
>> immediately
>> and delete the original.
>>
>
Re: Question about @OneToMany
Posted by pietia <pi...@gmail.com>.
hi there !
Is possible to define @OneToMany realtionship
without using join table ? (i saw that in book about Ejb 3.0).
i use openjpa and when i'm trying to do simple
realtionship A-B, as follows :
@Entity
public class Address implements Serializable {
private Integer id;
private String street;
private String city;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
...
}
@Entity
public class Customer implements Serializable {
private Integer id;
private String name;
private String surname;
private Collection<Address> address = new ArrayList<Address>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
@JoinColumn(name = "Address_id")
public Collection<Address> getAddress() {
return address;
}
...
}
Client:
public class Testuj {
public static void main(String[] args) {
Properties prop = new Properties();
prop.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.RemoteInitialContextFactory");
prop.put("java.naming.provider.url", "ejbd://localhost:4201");
try {
Context context = new InitialContext(prop);
try {
CustomerManagerRemote cmr = (CustomerManagerRemote) context
.lookup("CustomerManagerRemote");
Customer customer = new Customer();
customer.setName("Anna");
customer.setSurname("Maria");
ArrayList<Address> addresses = (ArrayList<Address>)
customer.getAddress();
Address address = new Address();
address.setCity("New York");
address.setStreet("Nieprawdopodna 12/123");
addresses.add(address);
customer.setAddress(addresses);
cmr.addCustomer(customer);
} catch (Exception e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
.. i gets:
javax.ejb.EJBException: The bean encountered a non-application exception.;
nested exception is:
<openjpa-1.0.2-r420667:627158 fatal user error>
org.apache.openjpa.persistence.ArgumentException: You have supplied columns
for "org.testowa.Customer.address", but this mapping cannot have columns in
this context.
at
org.apache.openejb.client.EJBInvocationHandler.convertException(EJBInvocationHandler.java:219)
at
org.apache.openejb.client.EJBObjectHandler._invoke(EJBObjectHandler.java:157)
at
org.apache.openejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:117)
at
org.apache.openejb.client.proxy.Jdk13InvocationHandler.invoke(Jdk13InvocationHandler.java:52)
at $Proxy0.addCustomer(Unknown Source)
at org.testowa.Testuj.main(Testuj.java:44)
Caused by: <openjpa-1.0.2-r420667:627158 fatal user error>
org.apache.openjpa.persistence.ArgumentException: You have supplied columns
for "org.testowa.Customer.address", but this mapping cannot have columns in
this context.
at
org.apache.openjpa.jdbc.meta.MappingInfo.assertNoSchemaComponents(MappingInfo.java:327)
at
org.apache.openjpa.jdbc.meta.strats.RelationToManyTableFieldStrategy.map(RelationToManyTableFieldStrategy.java:96)
at
org.apache.openjpa.jdbc.meta.strats.RelationCollectionTableFieldStrategy.map(RelationCollectionTableFieldStrategy.java:94)
at
org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:120)
at
org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:80)
at
org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:438)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:403)
at
org.apache.openjpa.jdbc.meta.ClassMapping.resolveMapping(ClassMapping.java:812)
at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1618)
at
org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:675)
at
org.apache.openjpa.meta.MetaDataRepository.resolveMapping(MetaDataRepository.java:636)
at
org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:514)
at
org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:302)
at
org.apache.openjpa.jdbc.meta.MappingRepository.getMapping(MappingRepository.java:282)
at
org.apache.openjpa.jdbc.meta.MappingTool.getMapping(MappingTool.java:673)
at
org.apache.openjpa.jdbc.meta.MappingTool.buildSchema(MappingTool.java:745)
at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:643)
at
org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:164)
at
org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:130)
at
org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:188)
at
org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:142)
at
org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:192)
at
org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:56)
at
org.apache.geronimo.persistence.CMPEntityManagerTxScoped.createEntityManager(CMPEntityManagerTxScoped.java:74)
at
org.apache.geronimo.persistence.CMPEntityManagerTxScoped.getEntityManager(CMPEntityManagerTxScoped.java:55)
at
org.apache.geronimo.persistence.CMPEntityManagerTxScoped.persist(CMPEntityManagerTxScoped.java:81)
at org.testowa.CustomerManagerBean.addCustomer(CustomerManagerBean.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:158)
at
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:141)
at
org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:67)
at
org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:210)
at
org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:188)
at
org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:165)
at
org.apache.openejb.server.ejbd.EjbRequestHandler.doEjbObject_BUSINESS_METHOD(EjbRequestHandler.java:238)
at
org.apache.openejb.server.ejbd.EjbRequestHandler.processRequest(EjbRequestHandler.java:129)
at
org.apache.openejb.server.ejbd.EjbDaemon.processEjbRequest(EjbDaemon.java:164)
at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:122)
at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:84)
at org.apache.openejb.server.ejbd.EjbServer.service(EjbServer.java:60)
at org.apache.openejb.server.ServicePool$2.run(ServicePool.java:78)
at org.apache.openejb.server.ServicePool$3.run(ServicePool.java:101)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
what may be wronq ?
pietia
--
View this message in context: http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17170612.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Question about @OneToMany
Posted by Andy Schlaikjer <ha...@cs.cmu.edu>.
I think it's not wonderful that you have to add an extra field to your
object model if you're really not interested in modeling the ManyToOne
side of a relationship like this. However, at the moment you can't
"reuse" a single table to map both an entity and a join table, so we're
stuck.
For example, this doesn't work:
@Entity
public class Node
{
@Id
protected long id;
@OneToMany()
@JoinTable(
name = "Node",
joinColumns = @JoinColumn(name = "parent_id"), // i wish
inverseJoinColumns = @JoinColumn(name = "id")
)
protected Collection<Node> children;
...
}
Michael Vorburger wrote:
> Hello,
>
> Similar situation here, and I wonder about people's thoughts & pros/cons
> regarding this:
>
>> Your solution (anotate "ModelObject parent;" with @ManyToOne instead
> of @Transient and add mappedBy="parent" to @OneToMany) works, also for
> my application, but turns the uni-directional relation into a
> bi-directional relation. And this bi-directional relation is more
> dificult to manage and not needed in our Java application.
>
> Why is this "bi-directional relation is more dificult to manage and not
> needed in our Java application" ? If you let OpenJPA deal with this for
> you with the Managed Inverses
> (http://openjpa.apache.org/docs/latest/manual/ref_guide_inverses.html),
> what's the problem with an additional field? Hide it even - if for some
> reason you don't want to expose the bi-directionality to the users of
> the object model for keep that '@ManyToOne ModelObject parent' as a
> private with no setters and getters - just to get the desired mapping!
>
> What's the issue with this approach? (Portability and not wanting to
> use Managed Inverses aside; but I don't know if that's strong enough,
> you're using OpenJPA specific configuration elsewhere already, and
> that's really what this is - a runtime configuration specific to one JPA
> implementation. Other implementations may have a similar feature? If
> not, worst case, when switching, manually code the logic [with loop
> detection, if needed]).
>
> Regards,
> Michael
>
>
> -----Original Message-----
> From: Uden [mailto:udenvh@gmail.com]
> Sent: jeudi, 8. mai 2008 21:37
> To: users@openjpa.apache.org
> Subject: Re: Question about @OneToMany
>
>
> Hi Andy, thanks for the quick response.
>
> In my application i had three tables generated (a master, a detail and a
> join table) for what i believed could be modelled by just the master and
> a detail table (at least in traditional database modeling). So when i
> was looking for a solution to simplify my datamodel in the database, i
> found this posting which looked similar to my problem and added my
> question.
>
> I need to map the following Java classes (note i reuse Marco's code
> example):
>
> @MappedSuperclass
> @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
> class ModelObject {
>
> @Id
> private int id
>
> @Transient
> ModelObject parent;
>
> @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
> List<ModelObject> children;
>
> .....
> }
>
> @Entity
> class Company extends ModelObject {
> }
>
> @Entity
> class Employer extends ModelObject {
> }
>
> to the folowing database tables:
>
> COMPANY
> (ID (PK)
> , ...
> )
>
> and EMPLOYEE
> (ID (PK)
> ,COMPANY_ID (FK to COMPANY.ID)
> , ...
> )
>
> In Marco's original question he indicates that in his case "openjpa
> create 4 tables (Company, Company_children, Emplpyer and
> Employer_children).".
> Your solution (anotate "ModelObject parent;" with @ManyToOne instead of
> @Transient and add mappedBy="parent" to @OneToMany) works, also for my
> application, but turns the uni-directional relation into a
> bi-directional relation.
> And this bi-directional relation is more dificult to manage and not
> needed in our Java application. It does however results in a simpler
> datamodel.
>
> Your second solution changes the direction (or ownership) of the
> relation in the Java model.
>
> So it seems we have to trade a simplified database datamodel versus a
> simplified Java datamodel.
>
> Or is there an other solution?
>
> thanks,
> Uden
>
>
> hazen wrote:
>> Hi Uden,
>>
>> If you'd rather keep the relation unidirectional just remove the
>> `children` field-- the `parent` field alone is enough to encode the
>> relation without recourse to a separate join table. Either way, I
>> don't see how the quoted section below results in a join table. Both
>> fields rely solely on a "parent_id" column within the "ModelObject"
>> table, not on some other join table. Am I missing something?
>>
>> Andy
>>
>> Uden wrote:
>>> The solution quoted below but has a consequence for the Java class
> model:
>>> the
>>> OneToMany relationship becomes bi-directional instead of
> uni-directional.
>>> What is the reason for creating the join-table?
>>>
>>> I thought (based on my database experience) that a join-table is only
>
>>> required for ManyToMany relationships.
>>> If you look at the data in the join-table of a uni-directional
>>> relation (no mappedBy attribute), the relation between the join-table
>
>>> and master table is always OneToOne, so this relation could be
>>> handled by a FK-field in the detail-table.
>>>
>>> thanks for your explanation,
>>> Uden
>>>
>>>
>>> Andy Schlaikjer-2 wrote:
>>>> Marco Schwarz wrote:
>>>>> How can I make only 2 tables?
>>>> Here's my guess:
>>>>
>>>> First, use the "mappedBy" property of the @OneToMany annotation,
>>>> like
>>>> this:
>>>>
>>>> @Entity
>>>> class ModelObject {
>>>> ...
>>>>
>>>> @ManyToOne
>>>> ModelObject parent;
>>>>
>>>> @OneToMany(mappedBy="parent")
>>>> List<ModelObject> children;
>>>>
>>>> ...
>>>> }
>>>>
>>>> This way, an extra join table won't be necessary to encode the
>>>> parent child relationship. Only the "parent_id" column in the
> "ModelObject"
>>>> table will be used to encode the relationship.
>>>>
>>
>
> --
> View this message in context:
> http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17134828.ht
> ml
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>
>
> ____________________________________________________________
>
> • This email and any files transmitted with it are CONFIDENTIAL and intended
> solely for the use of the individual or entity to which they are addressed.
> • Any unauthorized copying, disclosure, or distribution of the material within
> this email is strictly forbidden.
> • Any views or opinions presented within this e-mail are solely those of the
> author and do not necessarily represent those of Odyssey Financial
> Technologies SA unless otherwise specifically stated.
> • An electronic message is not binding on its sender. Any message referring to
> a binding engagement must be confirmed in writing and duly signed.
> • If you have received this email in error, please notify the sender immediately
> and delete the original.
>
RE: Question about @OneToMany
Posted by Michael Vorburger <mv...@odyssey-group.com>.
Hello,
Similar situation here, and I wonder about people's thoughts & pros/cons
regarding this:
> Your solution (anotate "ModelObject parent;" with @ManyToOne instead
of @Transient and add mappedBy="parent" to @OneToMany) works, also for
my application, but turns the uni-directional relation into a
bi-directional relation. And this bi-directional relation is more
dificult to manage and not needed in our Java application.
Why is this "bi-directional relation is more dificult to manage and not
needed in our Java application" ? If you let OpenJPA deal with this for
you with the Managed Inverses
(http://openjpa.apache.org/docs/latest/manual/ref_guide_inverses.html),
what's the problem with an additional field? Hide it even - if for some
reason you don't want to expose the bi-directionality to the users of
the object model for keep that '@ManyToOne ModelObject parent' as a
private with no setters and getters - just to get the desired mapping!
What's the issue with this approach? (Portability and not wanting to
use Managed Inverses aside; but I don't know if that's strong enough,
you're using OpenJPA specific configuration elsewhere already, and
that's really what this is - a runtime configuration specific to one JPA
implementation. Other implementations may have a similar feature? If
not, worst case, when switching, manually code the logic [with loop
detection, if needed]).
Regards,
Michael
-----Original Message-----
From: Uden [mailto:udenvh@gmail.com]
Sent: jeudi, 8. mai 2008 21:37
To: users@openjpa.apache.org
Subject: Re: Question about @OneToMany
Hi Andy, thanks for the quick response.
In my application i had three tables generated (a master, a detail and a
join table) for what i believed could be modelled by just the master and
a detail table (at least in traditional database modeling). So when i
was looking for a solution to simplify my datamodel in the database, i
found this posting which looked similar to my problem and added my
question.
I need to map the following Java classes (note i reuse Marco's code
example):
@MappedSuperclass
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
class ModelObject {
@Id
private int id
@Transient
ModelObject parent;
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
List<ModelObject> children;
.....
}
@Entity
class Company extends ModelObject {
}
@Entity
class Employer extends ModelObject {
}
to the folowing database tables:
COMPANY
(ID (PK)
, ...
)
and EMPLOYEE
(ID (PK)
,COMPANY_ID (FK to COMPANY.ID)
, ...
)
In Marco's original question he indicates that in his case "openjpa
create 4 tables (Company, Company_children, Emplpyer and
Employer_children).".
Your solution (anotate "ModelObject parent;" with @ManyToOne instead of
@Transient and add mappedBy="parent" to @OneToMany) works, also for my
application, but turns the uni-directional relation into a
bi-directional relation.
And this bi-directional relation is more dificult to manage and not
needed in our Java application. It does however results in a simpler
datamodel.
Your second solution changes the direction (or ownership) of the
relation in the Java model.
So it seems we have to trade a simplified database datamodel versus a
simplified Java datamodel.
Or is there an other solution?
thanks,
Uden
hazen wrote:
>
> Hi Uden,
>
> If you'd rather keep the relation unidirectional just remove the
> `children` field-- the `parent` field alone is enough to encode the
> relation without recourse to a separate join table. Either way, I
> don't see how the quoted section below results in a join table. Both
> fields rely solely on a "parent_id" column within the "ModelObject"
> table, not on some other join table. Am I missing something?
>
> Andy
>
> Uden wrote:
>> The solution quoted below but has a consequence for the Java class
model:
>> the
>> OneToMany relationship becomes bi-directional instead of
uni-directional.
>>
>> What is the reason for creating the join-table?
>>
>> I thought (based on my database experience) that a join-table is only
>> required for ManyToMany relationships.
>> If you look at the data in the join-table of a uni-directional
>> relation (no mappedBy attribute), the relation between the join-table
>> and master table is always OneToOne, so this relation could be
>> handled by a FK-field in the detail-table.
>>
>> thanks for your explanation,
>> Uden
>>
>>
>> Andy Schlaikjer-2 wrote:
>>> Marco Schwarz wrote:
>>>> How can I make only 2 tables?
>>> Here's my guess:
>>>
>>> First, use the "mappedBy" property of the @OneToMany annotation,
>>> like
>>> this:
>>>
>>> @Entity
>>> class ModelObject {
>>> ...
>>>
>>> @ManyToOne
>>> ModelObject parent;
>>>
>>> @OneToMany(mappedBy="parent")
>>> List<ModelObject> children;
>>>
>>> ...
>>> }
>>>
>>> This way, an extra join table won't be necessary to encode the
>>> parent child relationship. Only the "parent_id" column in the
"ModelObject"
>>> table will be used to encode the relationship.
>>>
>>
>
>
--
View this message in context:
http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17134828.ht
ml
Sent from the OpenJPA Users mailing list archive at Nabble.com.
____________________________________________________________
� This email and any files transmitted with it are CONFIDENTIAL and intended
solely for the use of the individual or entity to which they are addressed.
� Any unauthorized copying, disclosure, or distribution of the material within
this email is strictly forbidden.
� Any views or opinions presented within this e-mail are solely those of the
author and do not necessarily represent those of Odyssey Financial
Technologies SA unless otherwise specifically stated.
� An electronic message is not binding on its sender. Any message referring to
a binding engagement must be confirmed in writing and duly signed.
� If you have received this email in error, please notify the sender immediately
and delete the original.
Re: Question about @OneToMany
Posted by Uden <ud...@gmail.com>.
Hi Andy, thanks for the quick response.
In my application i had three tables generated (a master, a detail and a
join table) for what i believed could be modelled by just the master and a
detail table (at least in traditional database modeling). So when i was
looking for a solution to simplify my datamodel in the database, i found
this posting which looked similar to my problem and added my question.
I need to map the following Java classes (note i reuse Marco's code
example):
@MappedSuperclass
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
class ModelObject {
@Id
private int id
@Transient
ModelObject parent;
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
List<ModelObject> children;
.....
}
@Entity
class Company extends ModelObject {
}
@Entity
class Employer extends ModelObject {
}
to the folowing database tables:
COMPANY
(ID (PK)
, ...
)
and EMPLOYEE
(ID (PK)
,COMPANY_ID (FK to COMPANY.ID)
, ...
)
In Marco's original question he indicates that in his case "openjpa create 4
tables (Company,
Company_children, Emplpyer and Employer_children).".
Your solution (anotate "ModelObject parent;" with @ManyToOne instead of
@Transient and add mappedBy="parent" to @OneToMany) works, also for my
application, but turns the uni-directional relation into a bi-directional
relation.
And this bi-directional relation is more dificult to manage and not needed
in our Java application. It does however results in a simpler datamodel.
Your second solution changes the direction (or ownership) of the relation in
the Java model.
So it seems we have to trade a simplified database datamodel versus a
simplified Java datamodel.
Or is there an other solution?
thanks,
Uden
hazen wrote:
>
> Hi Uden,
>
> If you'd rather keep the relation unidirectional just remove the
> `children` field-- the `parent` field alone is enough to encode the
> relation without recourse to a separate join table. Either way, I don't
> see how the quoted section below results in a join table. Both fields
> rely solely on a "parent_id" column within the "ModelObject" table, not
> on some other join table. Am I missing something?
>
> Andy
>
> Uden wrote:
>> The solution quoted below but has a consequence for the Java class model:
>> the
>> OneToMany relationship becomes bi-directional instead of uni-directional.
>>
>> What is the reason for creating the join-table?
>>
>> I thought (based on my database experience) that a join-table is only
>> required for ManyToMany relationships.
>> If you look at the data in the join-table of a uni-directional relation
>> (no
>> mappedBy attribute), the relation between the join-table and master table
>> is
>> always OneToOne, so this relation could be handled by a FK-field in the
>> detail-table.
>>
>> thanks for your explanation,
>> Uden
>>
>>
>> Andy Schlaikjer-2 wrote:
>>> Marco Schwarz wrote:
>>>> How can I make only 2 tables?
>>> Here's my guess:
>>>
>>> First, use the "mappedBy" property of the @OneToMany annotation, like
>>> this:
>>>
>>> @Entity
>>> class ModelObject {
>>> ...
>>>
>>> @ManyToOne
>>> ModelObject parent;
>>>
>>> @OneToMany(mappedBy="parent")
>>> List<ModelObject> children;
>>>
>>> ...
>>> }
>>>
>>> This way, an extra join table won't be necessary to encode the parent
>>> child relationship. Only the "parent_id" column in the "ModelObject"
>>> table will be used to encode the relationship.
>>>
>>
>
>
--
View this message in context: http://www.nabble.com/Question-about-%40OneToMany-tp16840368p17134828.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Question about @OneToMany
Posted by Andy Schlaikjer <ha...@cs.cmu.edu>.
Hi Uden,
If you'd rather keep the relation unidirectional just remove the
`children` field-- the `parent` field alone is enough to encode the
relation without recourse to a separate join table. Either way, I don't
see how the quoted section below results in a join table. Both fields
rely solely on a "parent_id" column within the "ModelObject" table, not
on some other join table. Am I missing something?
Andy
Uden wrote:
> The solution quoted below but has a consequence for the Java class model: the
> OneToMany relationship becomes bi-directional instead of uni-directional.
>
> What is the reason for creating the join-table?
>
> I thought (based on my database experience) that a join-table is only
> required for ManyToMany relationships.
> If you look at the data in the join-table of a uni-directional relation (no
> mappedBy attribute), the relation between the join-table and master table is
> always OneToOne, so this relation could be handled by a FK-field in the
> detail-table.
>
> thanks for your explanation,
> Uden
>
>
> Andy Schlaikjer-2 wrote:
>> Marco Schwarz wrote:
>>> How can I make only 2 tables?
>> Here's my guess:
>>
>> First, use the "mappedBy" property of the @OneToMany annotation, like
>> this:
>>
>> @Entity
>> class ModelObject {
>> ...
>>
>> @ManyToOne
>> ModelObject parent;
>>
>> @OneToMany(mappedBy="parent")
>> List<ModelObject> children;
>>
>> ...
>> }
>>
>> This way, an extra join table won't be necessary to encode the parent
>> child relationship. Only the "parent_id" column in the "ModelObject"
>> table will be used to encode the relationship.
>>
>