Performance bottleneck with EclipsLink 2.0 - jpa

Recently while I was using EclipsLink 2.0 I run into performance bottleneck problem with my implementation of persisting objects.
To be more specific I used to have the following implementation:
#Entity
#Table(name = "CUSTOMERS")
public class CustomerEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private volatile Long id;
#Column(nullable = false, unique = true)
private String name;
private static final long serialVersionUID = 6952530957072210017L;
private String custGroup;
private String address;
private String nameOfFirstPerson;
private String contactPerson;
private String phone;
private String fax;
private String email;
private String comments;
private String defaultCustomer;
private volatile boolean delayedPaymentAllowed;
private volatile long periodOfDelayedPaymentAllowed;
private volatile boolean restrictionsOnDelayedPayment;
private volatile double maxAmoutPemittedSom;
private volatile double maxAmoutPemittedYE;
private transient String salesPointName;
#Column(length=25483)
private HashMap<String, PriceItem> totalBalance;
#Column(length=25483)
private HashMap<String, PriceItem> totalBalanceUsd;
private transient boolean valueChanged = false;
#OneToMany(mappedBy = "supplier")
private Collection<PurchaseInvoiceEntity> purchaseInvoices;
#OneToMany(mappedBy = "receiver")
private Collection<SalesInvoiceEntity> salesInvoices;
#OneToMany(mappedBy = "payer")
private Collection<PayInSlipEntity> payInSlips;
#OneToMany(mappedBy = "recipient")
private Collection<PaymentOrderEntity> paymentOrders;
#OneToMany(mappedBy = "recipient")
private Collection<WriteOffEntity> writeOffs;
#ManyToOne()
private ResponsiblePersonForDebtEntity responsiblePersonForDebt;
#ManyToOne
private CustomerGroupEntity customerGroup;
public CustomerEntity() {
valueChanged = false;
}
...
}
and while each time I was adding an instance of new document into appropriate Collection while inserting a new instance of document into a table I detected that it takes too long to insert the document. I come across of this problem while I was using profiler module of netbeans ide 6.9. Actually I was using these collections in order to check for emptiness with related documents.

In order to tackle the problem I simply applied the following solution:
I simply removed document references :
#OneToMany(mappedBy = "supplier")
private Collection purchaseInvoices;
#OneToMany(mappedBy = "receiver")
private Collection salesInvoices;
#OneToMany(mappedBy = "payer")
private Collection payInSlips;
#OneToMany(mappedBy = "recipient")
private Collection paymentOrders;
#OneToMany(mappedBy = "recipient")
private Collection writeOffs;
from the CusotmerEntity:
#Entity
#Table(name = "CUSTOMERS")
public class CustomerEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private volatile Long id;
#Column(nullable = false, unique = true)
private String name;
private static final long serialVersionUID = 6952530957072210017L;
private String custGroup;
private String address;
private String nameOfFirstPerson;
private String contactPerson;
private String phone;
private String fax;
private String email;
private String comments;
private String defaultCustomer;
private volatile boolean delayedPaymentAllowed;
private volatile long periodOfDelayedPaymentAllowed;
private volatile boolean restrictionsOnDelayedPayment;
private volatile double maxAmoutPemittedSom;
private volatile double maxAmoutPemittedYE;
private transient String salesPointName;
#Column(length = 25483)
private HashMap<String, PriceItem> totalBalance;
#Column(length = 25483)
private HashMap<String, PriceItem> totalBalanceUsd;
private transient boolean valueChanged = false;
#ManyToOne()
private ResponsiblePersonForDebtEntity responsiblePersonForDebt;
#ManyToOne
private CustomerGroupEntity customerGroup;
public CustomerEntity() {
valueChanged = false;
}
.....}
while checking for references for the documents I used JPA query while editing or deleting CustomerEntity.
This simple change removed the most affecting performance problem.
Side Note:
Please while using performance profiler include a check for package methods too(eclipslink for ex.)

For performance and scalability issues in JPA please read or listen S"Strategies and Best Practices for Highly Scalable Java Persistence Applications" by Gordon Yorke.

Related

Load tables only with some specific conditions (#Where)

What I'm trying to do is to load only promotions with promotion.enabled=1 AND PromotionType.enabled=1.
I tried to add the #Where annotation in both tables but when I set promotionType, enabled to 0 I´m getting an error.
On the other hand, I also tried to add the #WhereJoinTable clause to promotionType but I'm not getting the expected result. Any help?
The first one:
#Entity
#Table(name = "HOTEL_PROMOTION")
#Where(clause = "enabled=1")
public class Promotion implements Serializable {
private static final long serialVersionUID = 257070400893576505L;
#Id
#Column(name = "PROMOTION_ID")
private Long id;
#Column(name = "CODE")
private String code;
#Column(name = "NAME")
private String name;
#Column(name = "PRIORITY")
private Long priority;
#ManyToOne
#JoinColumn(name = "PROMOTION_TYPE_ID")
#WhereJoinTable(clause = "enabled=1")
private PromotionType promotionType;
#Column(name = "ENABLED")
private Boolean enabled;
}
The second one:
#Entity
#Table(name = "HOTEL_PROMOTION_TYPE")
public class PromotionType implements Serializable {
private static final long serialVersionUID = -8359165117733458987L;
#Id
#Column(name = "PROMOTION_TYPE_ID")
private Long id;
#Column(name = "CODE")
private String code;
#Column(name = "NAME")
private String name;
#Column(name = "STYLE")
private String style;
#Column(name = "ENABLED")
private Boolean enabled;
}

org.springframework.dao.InvalidDataAccessResourceUsageException in spring data jpa

i have (one to many) and (many to one) bi-directional mappings while i am querying with #Query with spring- data-jpa using repository using foreign key iam getting InvalidDataAccessApiUsageException
#Entity(name="docket")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Docket implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name="docket_Id")
private long Id;
#Column(name="docket_name")
private String docket_name;
#Column(name="area_in_kms")
private long area_in_kms;
#Column(name="number_of_connections")
private long number_of_connections;
#Column(name="number_of_sewer_connections")
private long number_of_sewer_connections;
#Column(name="number_of_manholes")
private long number_of_manholes;
#Column(name="deep_manholes")
private long deep_manholes;
#Column(name="contour_low")
private long contour_low;
#Column(name="contour_high")
private long contour_high;
#Column(name="length_of_sewermain_kms")
private long length_sewer_in_kms;
#JsonBackReference(value="section-details")
#ManyToOne(cascade= CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "section_Id")
private Section section;
#Entity(name="section")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Section implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="section_Id")
private long Id;
#Column(name="section_name")
private String section_name;
#Column(name="area_in_kms")
private long area_in_kms;
#Column(name="calculated_length")
private long calculated_length;
#Column(name="area_geometry")
private long area_geometry;
//#JsonManagedReference
#OneToMany(mappedBy = "section", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private Set<Docket> docket;
#Repository
#Transactional(readOnly = true)
public interface DocketRepository extends JpaRepository<Docket, Long> {
#Modifying(clearAutomatically = true)
#Query(nativeQuery=true,value= "select d from docket d where d.section_id = :section_id" )
List<Docket> findAlldocketsforsection(#Param("section_id") long id);
need help!! on this i need to query more custom queries in this api please suggest me from where i am getting error

JPA query with OneToOne lazy

I have this structure of object
#Entity
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long memberId;
private String name;
private boolean man;
private String address;
#OneToOne(fetch = FetchType.LAZY)
private City city;
private String postalCode;
private String phone1;
private String phone2;
private LocalDate birthdate;
private String email;
private String emergencyContactName;
private String emergencyPhone;
private String paymentGatewayKey;
#OneToMany(fetch = FetchType.LAZY)
private List<Contract> contracs;
#OneToOne(fetch = FetchType.LAZY)
private Commerce commerce;
}
#Entity
public class Contract {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long contractId;
private BigDecimal price;
private int frequency;
private int term;
private LocalDate startDate;
private LocalDate endDate;
private int numberOfPayment;
#Enumerated(EnumType.STRING)
private StatusEnum status;
#OneToMany(fetch = FetchType.LAZY,mappedBy = "contract")
private List<Payment> payments;
#ManyToOne
private Member member;
}
#Entity
public class Payment {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long paymentId;
private BigDecimal price;
private LocalDate date;
#Enumerated(EnumType.STRING)
private StatusEnum status;
#Enumerated(EnumType.STRING)
private PaymentModeEnum paymentMode;
#ManyToOne
private Contract contract;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private List<Operation> operations;
}
is it possible from a member query to get only the needed contract, payment, city and commerce info?
If member have many contract... i want to get only contract #2...
I started this query but city and commerce are lazy and i don't know what to do with theses fields.
select m from Member m inner join fetch m.contracs c inner join fetch c.payments p where c.contractId = :contractId

JPA JOIN without cross joins

I'm trying to have a relationship between the following tables
COMBINE
#Entity
#NamedQuery(name="Combine.findAll", query="SELECT c FROM Combine c")
#Table(name="COMBINE")
public class Combine implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private int artistid;
private int automated;
private int eventid;
private int locationid;
#Column(name="main_artist")
private int mainArtist;
public Combine() {
}
Event
#Entity
#NamedQuery(name="Event.findAll", query="SELECT e FROM Event e")
#Table(name="event")
public class Event implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private boolean active;
private String addbyspider;
private int automated;
#Lob
private String description;
private Timestamp doorsopen;
private Timestamp endtime;
private Timestamp lastfm;
#Column(name="latest_update")
private Timestamp latestUpdate;
private int minimumageid;
private String name;
private Timestamp nolatertime;
private int podiuminfo;
#Column(name="short_description")
private String shortDescription;
#Column(name="sold_out")
private int soldOut;
private Timestamp time;
#Column(name="update_by_bot")
private Timestamp updateByBot;
/* TO DO: LINK NAAR EVENTPRICE */
// public EventPrice getEventPrice() {
// return eventPrice;
// }
//
// public void setEventPrice(EventPrice eventPrice) {
// this.eventPrice = eventPrice;
// }
//
// #OneToOne(mappedBy = "event_price")
// private EventPrice eventPrice;
//bi-directional many-to-many association to Artist
//#ManyToMany(fetch = FetchType.LAZY)
#ManyToMany
#JoinTable(
name="COMBINE"
, joinColumns={
#JoinColumn(name="eventid")
}
, inverseJoinColumns={
#JoinColumn(name="artistid")
}
)
private List<Artist> artists;
#OneToOne
#JoinColumn(name="eventid")
private List<Combine> combine;
//bi-directional many-to-many association to Location
//#ManyToMany(fetch = FetchType.EAGER)
#OneToMany
#JoinTable(
name="COMBINE"
, joinColumns={
#JoinColumn(name="eventid")
}
, inverseJoinColumns={
#JoinColumn(name="locationid")
}
)
private List<Location> locations;
Location
#Entity
#NamedQuery(name="Location.findAll", query="SELECT l FROM Location l")
#Table(name="location")
public class Location implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private boolean active;
#Column(name="at_owner")
private int atOwner;
#Column(name="bad_ticket_site")
private int badTicketSite;
#Lob
private String description;
private int expectedBotItems;
private int expectedBotRuntime;
#Column(name="last_run")
private Timestamp lastRun;
private String name;
private boolean notPrimaryBot;
private int organisationid;
private short priorityid;
#Column(name="short_description")
private String shortDescription;
#Column(name="spider_by")
private int spiderBy;
What this currently does is generate cross joins with the tables with the following TypedQuery
StringBuffer sb = new StringBuffer();
sb.append("SELECT e FROM Event e, Combine c, Location l ");
sb.append("where e.id = c.eventid and l.id = c.locationid ");
sb.append("and e.time>=NOW() and e.soldOut='0' and e.active>=1");
This generates
select event0_.id as id1_26_,
event0_.active as active2_26_,
event0_.addbyspider as addbyspi3_26_,
event0_.automated as automate4_26_,
event0_.description as descript5_26_,
event0_.doorsopen as doorsope6_26_,
event0_.endtime as endtime7_26_,
event0_.lastfm as lastfm8_26_,
event0_.latest_update as latest_u9_26_,
event0_.minimumageid as minimum10_26_,
event0_.name as name11_26_,
event0_.nolatertime as nolater12_26_,
event0_.podiuminfo as podiumi13_26_,
event0_.short_description as short_d14_26_,
event0_.sold_out as sold_ou15_26_,
event0_.time as time16_26_,
event0_.update_by_bot as update_17_26_
from
event event0_
cross join COMBINE combine1_
cross join location location2_
where event0_.id=combine1_.eventid and location2_.id=combine1_.locationid and event0_.time>=now() and event0_.sold_out='0' and event0_.active>=1 limit ?
I do not want to create CROSS JOINS at all but instead I would like INNER JOIN between the tables. How could I achieve this?
There is something wrong with the OneToOne as it doesn't build to the server. Anyone know why this doesn't work?
#OneToOne
#JoinColumn(name="eventid")
private List<Combine> combine;

how to access to subproperties with jpa metamodel in where clause

I have a two entities with relation between they are.
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Integer id;
#NotNull
#Size(min = 3, max = 25)
private String firstName;
#NotNull
#Size(min = 3, max = 25)
private String lastName;
private String login;
private String password;
#OneToMany(mappedBy = "client")
private List<Project> projects;
}
and
public class Project implements Serializable {
private static final long serialVersionUID = 4762714047114442539L;
#Id
#GeneratedValue
private Integer id;
private String name;
#Temporal(TemporalType.TIMESTAMP)
private Date startDate;
#ManyToOne
#JoinColumn
private Client client;
}
I want to made a query using jpametamodel and Criteria API. Like this:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Project> q = cb.createQuery(Project.class);
Root<Project> projects = q.from(Project.class);
q.where(cb.equal(projects.get(Project_.client), clientId));
Problem for me that i don't know how to get access to "id" property of Client in this string:
q.where(cb.equal(projects.get(Project_.client), clientId));
i want to get something like
q.where(cb.equal(projects.get("client.id"), clientId));
but with jpametamodel. It is possible? :)
Tried something like this?
projects.get(Project_.client).get(Client_.id);