Hi,
the queries are not slow. There are just a hell lot of queries but you
are right. THe problem is that i ve done EAGER fetching quite
extensively and it makes no sense to load all positions when i just
want to show a list of orders in the first place. So i really need to
invest some more brain into fetch-groups or making more classes
transactional than just my DAOs.
Unfortantely i have problems with fetch-groups and detachment
currently. So things are crazy these days :)
It seems it was time that i get into problems so that i really dig
into the workings of OpenJPA. Good in the long run. Thx for your
support.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de
Am 08.04.2009 um 20:03 schrieb Paul Copeland:
Marc -
If all the join columns are indexed it should not be too slow. You
could put the same SQL into an "explain" analysis tool to
investigate it. For a start run the SQL outside JPA and see how
many rows are returned.
Notice you are getting an orderpos, an order, a boxes, and two
adresses in every row with these EAGER fetches (we don't see how
Address and Boxes are mapped). At some point the memory
requirements might be an issue. If the ResultSets are large and you
need all this in memory you might want to look into
openjpa.jdbc.LRSSize.
- Paul
On 4/8/2009 2:09 AM, Marc Logemann wrote:
Paul,
thx for pointing out that @ElementJoinColumn is definitely not
needed here. I removed them and at least everything works but
unfortunately as slow as before. My example was a simple one
because i dont wanted to show of the real one, but now since i
really dont know what to do, i must do it.
My Model ( i leave out some bits because of verbosiy):
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int oid;
@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "invaddress_oid", unique = true, nullable =
false, updatable = false)
Address invoiceAddress;
@OneToMany(mappedBy = "order" , cascade = CascadeType.ALL, fetch
= FetchType.EAGER)
List<DeliveryAddress> deliveryAddresses;
...
@Entity
public class DeliveryAddress extends Address {
@OneToMany(mappedBy = "deliveryAddress",cascade =
CascadeType.ALL, fetch = FetchType.EAGER)
List<OrderPosition> orderPositions;
@XmlTransient
@ManyToOne(cascade = CascadeType.REFRESH)
Order order;
...
@Entity
@Table(name = "orderpos")
public class OrderPosition {
@Id
long oid;
@ManyToOne(cascade = CascadeType.REFRESH)
@JoinColumn(name = "address_oid")
DeliveryAddress deliveryAddress;
Thats it. So basically i need some backreferences that when i query
for OrderPositions, i also get the parent DeliveryAddress. The same
for DeliveryAddress because i need infos on the Order. The DB looks
straighforward with foreign keys as usual.
Now my JPA Query is trivial: "select o FROM Order o"
This produces a SQL query for each and every OrderPosition like this:
[..]
[DEBUG http-8080-1 10:45:11] | <t 270855330, conn 1018597953>
executing prepstmnt 1716186906 SELECT t1.oid, t1.jpatype,
t1._version, t1.addresstype, t1.city, t1.company, t1.country,
t1.department, t1.email, t1.firstname, t1.gender, t1.lastname,
t1.middlename, t1.phone, t1.zip, t1.postofficebox, t1.street,
t1.housenr, t1.title, t2.oid, t2._version, t2.cleared, t2.id,
t2.lastused, t2.orderid, t2.boxtype, t1.deliverymode, t3.oid,
t3._version, t3.created, t3.createdymd, t3.custnr, t3.ordernr,
t4.oid, t4.jpatype, t4._version, t4.addresstype, t4.city,
t4.company, t4.country, t4.department, t4.email, t4.firstname,
t4.gender, t4.lastname, t4.middlename, t4.phone, t4.zip,
t4.postofficebox, t4.street, t4.housenr, t4.title, t4.box_oid,
t4.deliverymode, t4.ORDER_OID, t3.iscardowner, t3.cost,
t3.currency, t3.pricing, t3.paymenttype, t3.printed, t3.printedby,
t3.totalprice FROM orderpos t0 INNER JOIN address t1 ON
t0.address_oid = t1.oid LEFT OUTER JOIN boxes t2 ON t1.box_oid =
t2.oid LEFT OUTER JOIN orders t3 ON t1.ORDER_OID = t3.oid LEFT
OUTER JOIN address t4 ON t3.invaddress_oid = t4.oid WHERE t0.oid
= ? [params=(long) 37]
[DEBUG http-8080-1 10:45:11] | <t 270855330, conn 1018597953> [2
ms] spent
[DEBUG http-8080-1 10:45:11] | <t 270855330, conn 1018597953>
executing prepstmnt 1843485325 SELECT t1.oid, t1.jpatype,
t1._version, t1.addresstype, t1.city, t1.company, t1.country,
t1.department, t1.email, t1.firstname, t1.gender, t1.lastname,
t1.middlename, t1.phone, t1.zip, t1.postofficebox, t1.street,
t1.housenr, t1.title, t2.oid, t2._version, t2.cleared, t2.id,
t2.lastused, t2.orderid, t2.boxtype, t1.deliverymode, t3.oid,
t3._version, t3.created, t3.createdymd, t3.custnr, t3.ordernr,
t4.oid, t4.jpatype, t4._version, t4.addresstype, t4.city,
t4.company, t4.country, t4.department, t4.email, t4.firstname,
t4.gender, t4.lastname, t4.middlename, t4.phone, t4.zip,
t4.postofficebox, t4.street, t4.housenr, t4.title, t4.box_oid,
t4.deliverymode, t4.ORDER_OID, t3.iscardowner, t3.cost,
t3.currency, t3.pricing, t3.paymenttype, t3.printed, t3.printedby,
t3.totalprice FROM orderpos t0 INNER JOIN address t1 ON
t0.address_oid = t1.oid LEFT OUTER JOIN boxes t2 ON t1.box_oid =
t2.oid LEFT OUTER JOIN orders t3 ON t1.ORDER_OID = t3.oid LEFT
OUTER JOIN address t4 ON t3.invaddress_oid = t4.oid WHERE t0.oid
= ? [params=(long) 38]
[..]
As you can imagine, having thousands or even millions of
OrderPositions some time, this gets quite ugly. Now the big
question is, why is this the case? In my test DB i have "only" 1520
postions and even that produces a 14 seconds "wait" for the Queries
being processed.
Sorry for supplying so much text but i think you cant make it much
shorter. Right now i am quite clueless and this mapping is already
in production and each day it gets more worse grrrrr.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de
Am 08.04.2009 um 06:49 schrieb Paul Copeland:
Hi Marc -
I wonder what kind of database schema that produces. Normally you
would have OneToMany on one side and ManyToOne on the other side,
with the mappedBy on the OneToMany side. This is the classical
way the foreign keys work in relational database models. I think
you do not need ElementJoinColumn as the defaults will be right
(but I'm not sure without trying it).
So it would look like this -
public class Retoure {
@OneToMany(mappedBy="retoure", cascade = CascadeType.ALL, fetch =
FetchType.EAGER)
List<RetourePosition> retourePositionList;
}
public class RetourePosition {
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
Retoure retoure;
}
On 4/7/2009 5:14 PM, Marc Logemann wrote:
Hi,
i am getting this and because i have some severe performance
problems with our OpenJPA based app, i wanted to ask for help:
[INFO 02:06:25] Log4JLogFactory$LogAdapter.info(80) | Inefficient
mapping: You have declared that field
"de.logentis.bwh.model.RetourePosition.retoure" is mapped by
collection "de.logentis.bwh.model.Retoure.retourePositionList".
The mapping would be much more efficient if instead you map
"de.logentis.bwh.model.RetourePosition.retoure" and declare that
"de.logentis.bwh.model.Retoure.retourePositionList" is mapped by
it.
My domain model:
@Entity
@Table(name = "retoure")
@VersionColumn(name = "_version")
public class Retoure {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "oid")
long oid;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@ElementJoinColumn(name = "retoure_oid", referencedColumnName =
"oid")
List<RetourePosition> retourePositionList;
---
@Entity
@VersionColumn(name = "_version")
@Table(name = "retourepos")
public class RetourePosition {
@Id
@Column(name = "oid")
@GeneratedValue(strategy = GenerationType.IDENTITY)
long oid;
@OneToOne(mappedBy = "retourePositionList", cascade =
CascadeType.REFRESH, fetch = FetchType.EAGER)
Retoure retoure;
---
Table Info: "retoure_oid" is a foreign key field in the
"retourepos" table that points to the "oid" field of the
"retoure" table.
To me this looks like a good way but the warning says something
else. I tried to change the mapping so that the actual mapping
will be done in "retoure" atrtribute and just do a "mappedBy"
reference on "retourePositionList" but then it wont work at all.
When i read the warning, i would exactly expect that this would
work. So what am i doing wrong here?
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de