Showing posts with label O/R Mapping. Show all posts
Showing posts with label O/R Mapping. Show all posts

Thursday, May 29, 2014

hibernate inverse="true"

If inverse=”false”, unnecessary UPDATE statement will be executed.

Here is a article clearly explained this issue.
http://www.mkyong.com/hibernate/inverse-true-example-and-explanation/

When using annotation, mappedBy is equivalent to inverse = "true"

HQL delete does not honour cascades defined within hibernate mappings.

If deleting by HQL, you need delete children before you can delete the parent. It won't honor the cascade setting in the hibernate mappings.

hiberate cascade on ManyToOne

Normally cascade is put on OneToMany. One is considered as parent and many is considered as children. When parent is saved/updated/.../deleted, if there is cascade set, the same operation will happen on the children.

But hiberante also allows to put the cascade on the ManyToOne side.
Let see what happens if cascade is not set, when the child is going to be saved with a non-persistent parent object.
Here are the domains. DocPackage -> Document is one to many.

Here is the code

Hibernate will throw out this error.

Add cascade

Now run the same test, you can see the parent is inserted before the child is inserted.

What happens if the parent object already exists.

Here are the sql generated by hibernate. After the document is inserted, an update statement is triggered on package.

What happens if we delete the child record
If the document is the only document the package has, two delete statement are executed.

If the docuemnt is not the only document the package has,

All the operations above are triggered from document (the child object). Go back to the parent domain object DocPackage

mappedBy="docPackage" declares the Many side as owner of the relation. mappedBy refers to the property name of the association on the owner side(Document).
If uni-direction mapping, it is like this

Because this is uni-direction and the owner is DocPackage. All operations should be triggered from DocPackage.

Wednesday, May 28, 2014

Hibernate criteria examples

Here are the domain objects

Here is the example to query on grandchild's property.

Here is the example to query on different children's properties.

Thursday, May 8, 2014

hibernate count children records

Task and Comment are one to many.
Let's say we have a requirement displaying one task by its id, also displaying the total number of its comments.
Here is the way using criteria and projections to implement it.
A couple of things here...

  • We need add the task properties explicitly, line 6-8, otherwise the query only returns the count result.
  • The alias should be added, otherwise hibernate don't know how to map the result to the domain object. .add(Projections.property("task.id"), "id")
    • (I don't like the above two. It's kind of duplicating the task domain here)
  • criteria.setResultTransformer(Transformers.aliasToBean(Task.class)) tells hibernate to map the result to Task object. But Task does not have the property for commentsCount, we need add a transient property for it.


Good? Bad? like hibernate or hate hibernate? I would say it is not the neat way.
If you have neat way to implement it, let me know!

Sunday, April 6, 2014

Hibernate mapping to enum

Enum can be used directly in domain object.


Hibernate will save ordinal of the enum into database. FULL_TIME_EMPLOYEE is 0, PART_TIME_EMPLOYEE is 1... Hmm.... How about a new enum value is added between FULL_TIME and PART_TIME, the ordinal of PART_TIME will be changed to 2.
Use the annotation @Enumerated(EnumType.STRING), which will let hibernate save the string value of the enum.

Monday, November 25, 2013

hibernate interview questions

Top 50 Tricky Hibernate Interview Questions

1. What is Hibernate?

Ans: Hibernate is a powerful, high performance object/relational persistence and query service. This lets the users to develop persistent classes following object-oriented principles such as association, inheritance, polymorphism, composition, and collections.

2. What is ORM ?
Ans: ORM stands for Object/Relational mapping. It is the programmed and translucent perseverance of objects in a Java application in to the tables of a relational database using the metadata that describes the mapping between the objects and the database. It works by transforming the data from one representation to another.

3. Why hibernate is advantageous over Entity Beans & JDBC? 
Ans:
An entity bean always works under the EJB container, which allows reusing of the object external to the container. An object can not be detached in entity beans and in hibernate detached objects are supported.
Hibernate is not database dependent where as JDBC is database dependent. Query tuning is not needed for hibernate as JDBC is needed. Data can be placed in multiple cache which is supported by hibernate, whereas in JDBC the cache is to be implemented.

4. What are the different levels of ORM quality? 

Ans: There are four levels defined for ORMquality.

  • Pure relational
  • Light object mapping
  • Medium object mapping
  • Full object mapping
5. How will you configure Hibernate?
Ans: The configuration files hibernate.cfg.xml (or hibernate.properties) and mapping files *.hbm.xml are used by the Configuration class to create (i.e. configure and bootstrap hibernate) the SessionFactory, which in turn creates the Session instances. Session instances are the primary interface for the persistence service.

" hibernate.cfg.xml (alternatively can use hibernate.properties): These two files are used to configure the hibernate sevice (connection driver class, connection URL, connection username, connection password, dialect etc). If both files are present in the classpath then hibernate.cfg.xml file overrides the settings found in the hibernate.properties file.

" Mapping files (*.hbm.xml): These files are used to map persistent objects to a relational database. It is the best practice to store each object in an individual mapping file (i.e mapping file per class) because storing large number of persistent classes into one mapping file can be difficult to manage and maintain. The naming convention is to use the same name as the persistent (POJO) class name. For example Account.class will have a mapping file named Account.hbm.xml. Alternatively hibernate annotations can be used as part of your persistent class code instead of the *.hbm.xml files.
6. What are derived properties?
Ans: The properties that are not mapped to a column, but calculated at runtime by evaluation of an expression are called derived properties. The expression can be defined using the formula attribute of the element.
7. Define HibernateTemplate?
Ans: org.springframework.orm.hibernate.HibernateTemplate is a helper class which provides different methods for querying/retrieving data from the database. It also converts checked HibernateExceptions into unchecked DataAccessExceptions.
8. What are the benefits does HibernateTemplate provide?
Ans: The benefits of HibernateTemplate are :
  • HibernateTemplate, a Spring Template class simplifies interactions with Hibernate Session.
  • Common functions are simplified to single method calls.
  • Sessions are automatically closed.
  • Exceptions are automatically caught and converted to runtime exceptions.
9. What is the difference between sorted and ordered collection in hibernate?
Ans: sorted collection vs. order collection
sorted collection
order collection
A sorted collection is sorting a collection by utilizing the sorting features provided by the Java collections framework. The sorting occurs in the memory of JVM which running Hibernate, after the data being read from database using java comparator.
Order collection is sorting a collection by specifying the order-by clause for sorting this collection when retrieval.
If your collection is not large, it will be more efficient way to sort it.
If your collection is very large, it will be more efficient way to sort it .

10. What are the Collection types in Hibernate ?
Ans: 
  • Bag
  • Set
  • List
  • Array
  • Map
11. What is Hibernate proxy?
Ans: Mapping of classes can be made into a proxy instead of a table. A proxy is returned when actually a load is called on a session. The proxy contains actual method to load the data. The proxy is created by default by Hibernate, for mapping a class to a file. The code to invoke JDBC is contained in this class.
12. What is lazy fetching in hibernate ? 
Ans: Lazy fetching is associated with child objects loading for its parents. While loading the parent, the selection of loading a child object is to be specified / mentioned in the hbm.xml file. Hibernate does not load the whole child objects by default. Lazy=true means not to load the child objects.

13. Explain the difference between transient and detached objects in hibernate ?

Ans: Transient objects do not have association with the databases and session objects. They are simple objects and not persisted to the database. Once the last reference is lost, that means the object itself is lost. And of course , garbage collected. The commits and rollbacks will have no effects on these objects. They can become into persistent objects through the save method calls of Session object.

The detached object have corresponding entries in the database. These are persistent and not connected to the Session object. These objects have the synchronized data with the database when the session was closed. Since then, the change may be done in the database which makes this object stale. The detached object can be reattached after certain time to another object in order to become persistent again.
 

14. What are the core interfaces of Hibernate framework ?
Ans: 

  • Session Interface: The basic interface for all hibernate applications. The instances are light weighted and can be created and destroyed without expensive process.
  • SessionFactory interface: The delivery of session objects to hibernate applications is done by this interface. For the whole application, there will be generally one SessionFactory and can be shared by all the application threads.
  • Configuration Interface: Hibernate bootstrap action is configured by this interface. The location specification is specified by specific mapping documents, is done by the instance of this interface.
  • Transaction Interface: This is an optional interface. This interface is used to abstract the code from a transaction that is implemented such as a JDBC / JTA transaction.
  • Query and Criteria interface: The queries from the user are allowed by this interface apart from controlling the flow of the query execution.
15. What are the different types of caches in Hibernate ?
Ans
: Hibernate uses two different caches for objects: first-level cache and second-level cache. First-level cache is associated with the Session object, while second-level cache is associated with the SessionFactory object. By default, Hibernate uses first-level cache on a per-transaction basis. Hibernate uses this cache mainly to reduce the number of SQL queries it needs to generate within a given transaction.

16. How does the hibernate second-level cache work ?
Ans
: Hibernate always tries to first retrieve objects from the session and if this fails it tries to retrieve them from the second-level cache. If this fails again, the objects are directly loaded from the database. Hibernate's static initialize() method, which populates a proxy object, will attempt to hit the second-level cache before going to the database. The Hibernate class provides static methods for manipulation of proxies.

17. What is a query cache in Hibernate ?
Ans
: The query cache is responsible for caching the results and to be more precise the keys of the objects returned by queries. Let us have a look how Hibernate uses the query cache to retrieve objects. In order to make use of the query cache we have to modify the person loading example as follows.

Query query = session.createQuery("from Order as o where o.status=?");
query.setInt(0, "Active");
query.setCacheable(true); // the query is cacheable
List l = query.list();

18. What is callback interfaces in hibernate?
Ans
: Callback interfaces of hibernate are useful in receiving event notifications from objects. For example, when an object is loaded or deleted, an event is generated and notification is sent using callback interfaces.

19. What is the difference between and merge and update ?
Ans
: Use update() if you are sure that the session does not contain an already persistent instance with the same identifier, and merge() if you want to merge your modifications at any time without consideration of the state of the session.

20. What is the difference between and load() and get() ?
Ans
:
Load() method:

  • Only use the load() method if you are sure that the object exists.
  • load() method will throw an exception if the unique id is not found in the database.
  • load() just returns a proxy by default and database won't be hit until the proxy is first invoked.
Get() method:
  • If you are not sure that the object exists, then use one of the get()methods.
  • get() will hit the database immediately.
  • get() method will return null if the unique id is not found in the database.
21. What are the different caching strategies ?
Ans: Read-only: This strategy is useful for data that is read frequently but never updated. This is by far the simplest and best-performing cache strategy.
Read/write: Read/write caches may be appropriate if your data needs to be updated. They carry more overhead than read-only caches. In non-JTA environments, each transaction should be completed when Session.close() or Session.disconnect() is called.
Nonstrict read/write: This strategy does not guarantee that two transactions won't simultaneously modify the same data. Therefore, it may be most appropriate for data that is read often but only occasionally modified.
Transactional: This is a fully transactional cache that may be used only in a JTA environment.

22. What are the different fetching strategy in Hibernate ?
Ans
: Hibernate3 defines the following fetching strategies:
Join fetching - Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN.
Select fetching - a second SELECT is used to retrieve the associated entity or collection. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association.
Subselect fetching - a second SELECT is used to retrieve the associated collections for all entities retrieved in a previous query or fetch. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association.Batch fetching - an optimization strategy for select fetching - Hibernate retrieves a batch of entity instances or collections in a single SELECT, by specifying a list of primary keys or foreign keys.

23. What is version checking in Hibernate ?
Ans: version checking used in hibernate when more then one thread trying to access same data.
For example :
User A edit the row of the TABLE for update ( In the User Interface changing data This is user thinking time) and in the same time User B edit the same record for update and click the update. Then User A click the Update and update done. Chnage made by user B is gone. In hibernate you can perevent slate object updatation using version checking.

Check the version of the row when you are upding the row. Get the version of the row when you are fetching the row of the TABLE for update. On the time of updation just fetch the version number and match with your version number ( on the time of fetching).

24. Difference between getCurrentSession() and openSession() in Hibernate ?
Ans:

getCurrentSession():
The "current session" refers to a Hibernate Session bound by Hibernate behind the scenes, to the transaction scope. A Session is opened when getCurrentSession() is called for the first time and closed when the transaction ends.
openSession():
If you decide to use manage the Session yourself the go for sf.openSession(), you have to flush() and close() it. It does not flush and close() automatically.

25. What does session.refresh() do ?
Ans: It is possible to re-load an object and all its collections at any time, using the refresh() method. This is useful when database triggers are used to initialize some of the properties of the object.

26. How to get JDBC connections in hibernate ?
Ans: User Session.connection() method to get JDBC Connection.

27. What’s the use of session.lock() in hibernate ?
Ans: session.lock() method of session class is used to reattach an object which has been detached earlier. This method of reattaching doesn’t check for any data synchronization in database while reattaching the object and hence may lead to lack of synchronization in data.

28. What is the difference between the session.update() method and the session.lock() method ?
Ans: Both of these methods and saveOrUpdate() method are intended for reattaching a detached object. The session.lock() method simply reattaches the object to the session without checking or updating the database on the assumption that the database in sync with the detached object. It is the best practice to use either session.update(..) or session.saveOrUpdate(). Use session.lock() only if you are absolutely sure that the detached object is in sync with your detached object or if it does not matter because you will be overwriting all the columns that would have changed later on within the same transaction.

29. What is a SessionFactory?
Ans: The SessionFactory is the concept that is a single data store and thread safe. Because of this feature, many threads can access this concurrently and the sessions are requested, and also the cache that is immutable of compiled mappings for a specific database. A SessionFactory will be built only at the time of its startup. In order to access it in the application code, it should be wrapped in singleton. This wrapping makes the easy accessibility to it in an application code.

30. Explain about session interface?
Ans: This represents hibernate session which perform the manipulation on the database entities. Some of the activities performed by session interface are as follows they are managing the persistence state, fetching persisted ones and management of the transaction demarcation.


31. Explain about the dirty checking feature of Hibernate?
Ans: Dirty checking feature of the Hibernate allows users or developers to avoid time consuming data base write actions. This feature makes necessary updations and changes to the fields which require a change, remaining fields are left unchanged or untouched.

32. Explain the steps involved in creating database applications with Java using Hibernate?
Ans: Creating Database applications with Java is made simpler with Hibernate. First Plain old java object needs to be written, XML mapping file should be created which shows relationship between database and class attributes. Hibernate APIs can be used to store persistent objects.

33.Explain about hibernate.cfg.xml?
Ans: Hibernate can be configured with two types of files out of which hibernate.cfg.xmlis widely used and popular feature. Hibernate consults hibernate.cfg.xml file for its operating properties such as database dialect, connection string and mapping files. These files are searched on class path.

34. Explain about mapping description file?
Ans: Mapping description file is the second file which Hibernate uses to configure its functions. This mapping file has an extension *.hbm which instructs mapping between Java class and database tables. The usage of mapping description file rests entirely upon the business entity.

35. Explain about transaction file?
Ans: Transactions denote a work file which can save changes made or revert back the changes. A transaction can be started by session.beginTransaction() and it uses JDBC connection, CORBA or JTA. When this session starts several transactions may occur.

36. Explain about mapping files in Hibernate?
Ans: Mapping files forms the core of any database mapping tools. These files contain field to field mapping, usually this mapping occurs between classes and attributes. After mapping files they can be persist to the database. Tags can be used to indicate the presence of a primary key.

37. What is the effect when a transient mapped object is passed onto a Sessions save?
Ans: When a session.save( ) is passed to a transient mapped object it makes the method to become more persistent. Garbage collection and termination of the Java virtual machine stays as long as it is deleted explicitly. It may head back to its transient state.

38. Explain about version field?
Ans: Application level data integrity constants are important if you are making changes to offline information which is again backed by database. Higher level locking or versioning protocol is required to support them. Version field usage comes at this stage but the design and implementation process is left to the developer.

39. Explain State some advantages of hibernate?
Ans: Some of the advantages which a developer can get from Hibernate are as follows:
Mapping of one POJO table to one table is not required in hibernate.
It supports inheritance relationships and is generally a fast tool. Portability is necessary the greater benefit from hibernate. POJOs can be used in other applications where they are applicable.

40 Explain about addClass function?
Ans: This function translates a Java class name into file name. This translated file name is then loaded as an input stream from the Java class loader. This addclass function is important if you want efficient usage of classes in your code.

41. Explain about addjar() and addDirectory() methods?
Ans: These methods are the most convenient to use in hibernate. These methods allow you to load all your Hibernate documents at a time. These methods simplify code configuration, refactoring, layout, etc. These functions help you to add your hibernate mapping to Hibernate initialization files.

42. Explain about the id field?
Ans: This id field corresponds to the surrogate key which is generated by the database. These fields are handled by the id field. Name attribute is used to specify the names of the field and it should correspond to the method name of getid. This also should correspond to long type and the values should be stored I the database in the long column.

43. What are the most common methods of Hibernate configuration ?
Ans:The most common methods of Hibernate configuration are:

  • Programmatic configuration
  • XML configuration (hibernate.cfg.xml)
44. Define cascade and inverse option in one-many mapping ?
Ans:
cascade – enable operations to cascade to child entities.
cascade=”all|none|save-update|delete|all-delete-orphan”
inverse – mark this collection as the “inverse” end of a bidirectional association.

45. Explain Criteria API ?
Ans: Criteria is a simplified API for retrieving entities by composing Criterion objects. This is a very convenient approach for functionality like “search” screens where there is a variable number of conditions to be placed upon the result set.
Example :
List employees = session.createCriteria(Employee.class)
.add(Restrictions.like(“name”, “a%”) )
.add(Restrictions.like(“address”, “Boston”))
.addOrder(Order.asc(“name”) )
.list();

46. How can a whole class be mapped as immutable ?
Ans: Mark the class as mutable=”false” (Default is true),. This specifies that instances of the class are (not) mutable. Immutable classes, may not be updated or deleted by the application.

47. What  is hibernate tuning ?
Ans: The key to obtain better performance in any hibernate application is to employ SQL Optimization, session management, and Data caching.

48. What is HQL ?
Ans: HQL stands for Hibernate Query Language. Hibernate allows the user to express queries in its own portable SQL extension and this is called as HQL. It also allows the user to express in native SQL.

49. How to Execute Stored procedure in Hibernate ?
Ans:
<sql-query name="selectAllEmployees_SP" callable="true">
<return alias="emp" class="employee">
<return-property name="empid" column="EMP_ID"/>
<return-property name="name" column="EMP_NAME"/>
<return-property name="address" column="EMP_ADDRESS"/>
{ ? = call selectAllEmployees() }
</return>
</sql-query>

Code:
SQLQuery sq = (SQLQuery) session.getNamedQuery("selectAllEmployees_SP");
List results = sq.list();

50. What is a meant by light object mapping?
Ans:
The entities are represented as classes that are mapped manually to the relational tables. The code is hidden from the business logic using specific design patterns. This approach is successful for applications with a less number of entities, or applications with common, metadata-driven data models.


51.  Common Hibernate Performance Issues
Ans: 
Log SQL Statements in Production
N+1 Select Issue
Update Entities One by One
http://www.baeldung.com/hibernate-common-performance-problems-in-logs

Tuesday, September 17, 2013

ibatis #value# vs $value$

In Ibatis, normally we use “#” to wrap the variables passed in. 

SELECT * FROM table WHERE field1= #value# 


This generates prepared statement like this



SELECT * FROM table WHERE field1=?


When JDBC executes the prepared statement, it replaces the “?” with the real variable value sequentially.



In 99% scenarios, this works fine. But it does not work for this sql.



SELECT * FROM table WHERE fieldA=”How are you?” AND field1=#value#


JDBC injects the variable value right after “How are you”. Let’s the say the variable value is “A”, the query actually executed is



SELECT * FROM table WHERE fieldA=”How are youA” AND field1=?


For sure, it fails. How to fix it? Using the $Value$. When $Value$ is used, Ibatis does not generate prepared statement. It generates the sql directly, like this



SELECT * FROM table WHERE fieldA=”How are you?” AND field1=’A’


 



Usually, prepared statement has better performance. But it is not always true. Here is one case I faced in my project, the sql needs to look up data in oracle partitions. The partitions are separated by months. The query is like this



SELECT * FROM partition_table where date between #start_date# and #end_date#


The date parameter would be important for oracle to determine which partition to use for the query. If “#” is used, ibatis would generate prepared statement and also the query plan is generated at the same moment without knowing which partition to use. If “$” is used, oracle does know which partition to use when it generates the query plan. The result is that  the performance of using “$”is way better than using “#” in this specific scenario.

Thursday, February 11, 2010

JPA rolled back objects…

Our project is online ecommerce web site. When an order is made, the inventory record should be updated for inventory allocation. Two customers may buy the same product at the same time, one customer should get the optimistic lock exception. We definitely don’t want the order cannot be made just because optimistic lock exception. We want to catch the optimistic lock exception and retry the “update inventory”. We use spring aop to catch the exception.

@Around("execution(* com.elasticpath.service.catalog.InventoryService.processInventoryUpdate(..))" )
public Object doConcurrentOperation(final ProceedingJoinPoint pjp)
throws Throwable {
int timesRetried = 0;
while (true) {
try {
timesRetried++;
return pjp.proceed();
} catch (JpaOptimisticLockingFailureException oe) {
if (timesRetried >= NUM_ATTEMPTS_INVENTORY_ASSIGNMENT) {
LOG.error("Failed to allocate inventory. Aborting checkout attempt");
//throw new InventoryAllocationException("Allocation failed", oe);
throw oe;
}
try {
Thread.sleep(WAIT_TIME_FOR_CONCURRENCY);
} catch (InterruptedException e) {
// nothing to do...
}
}
}
}


If the exception happens, we run pjp.proceed() again. But we may get the exception below



Caused by:  org.apache.renamed.openjpa.persistence.InvalidStateException: The generated value processing detected an existing value assigned to this field: com.elasticpath.domain.catalog.impl.InventoryAuditImpl.uidPk.  This existing value was either provided via an initializer or by calling the setter method.  You either need to remove the @GeneratedValue annotation or modify the code to remove the initializer processing.
at org.apache.renamed.openjpa.util.ApplicationIds.assign(ApplicationIds.java:446)
at org.apache.renamed.openjpa.util.ApplicationIds.assign(ApplicationIds.java:426)
at org.apache.renamed.openjpa.jdbc.kernel.JDBCStoreManager.assignObjectId(JDBCStoreManager.java:541)


The field uidPk is primary key and automatically generated by openjpa. If it does not exist in database before, the uidPk will be 0. If this field is populated not by openjpa, the exception above was thrown out. When the exception happens, the transaction is rolled back. We expect the object should also be rolled back (set uidpk to be 0 and the state for that field  should be never changed), but it not always happens. Based on JPA specification, you should not use rolled back objects.



An alternative way is to backup the parameter and use the restore it before retry.



@Around("processInventoryUpdatePointcut() && args(inventoryAudit)")
public Object doConcurrentOperationForInventoryUpdate(final ProceedingJoinPoint pjp, final InventoryAudit inventoryAudit)
throws Throwable {
int timesRetried = 0;
LOG.debug("enter the method... timesRetried: " + timesRetried);

//The rolled back domain object may contains populated primary key
//use this object again will get InvalidStateException
InventoryAudit backedupInventoryAudit = (InventoryAudit) BeanUtils.cloneBean(inventoryAudit);
InventoryAudit inventoryAuditUsed = inventoryAudit;

while (true) {
try {
timesRetried++;
LOG.debug("before method proceed... timesRetried: " + timesRetried);
return pjp.proceed(new Object[]{inventoryAuditUsed});
} catch (JpaOptimisticLockingFailureException oe) {
LOG.warn("Failed to create order. Attempt: " + timesRetried);
if (timesRetried >= NUM_ATTEMPTS_INVENTORY_ASSIGNMENT) {
LOG.error("Failed to allocate inventory. Aborting checkout attempt");
//throw new InventoryAllocationException("Allocation failed", oe);
throw oe;
}
try {
Thread.sleep(WAIT_TIME_FOR_CONCURRENCY);
} catch (InterruptedException e) {
// nothing to do...
}
inventoryAuditUsed = (InventoryAudit) BeanUtils.cloneBean(backedupInventoryAudit);
}
}
}

Wednesday, January 13, 2010

OpenJpa bi-direction mappings

Let’s say we have Order and OrderPostEntry which relation is one to many.

In Order, it has a set of OrderPostEntry.

private Set<OrderPostEntry> orderPostEntries  = new HashSet<OrderPostEntry>();


In OrderPostEntry, it has the reference to Order.



        private Order order;

@ManyToOne(optional = false, targetEntity = OrderImpl.class)
@JoinColumn(name = "ORDER_UID")
@ForeignKey
public Order getOrder() {
return this.order;
}

public void setOrder(final Order order) {
this.order = order;
}


When the OrderPostEntry was added into Order, we want to the order will be set into each OrderPostEntry.



        @OneToMany(mappedBy = "order", targetEntity = OrderPostEntry.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public Set getOrderPostEntries() {
return orderPostEntries;
}

public void setOrderPostEntries(final Set orderPostEntries) {
for (OrderPostEntry orderPostEntry : orderPostEntries) {
orderPostEntry.setOrder(this);
}
this.orderPostEntries= orderPostEntries;
}


if you do so, you will get the exception "org.apache.renamed.openjpa.persistence.InvalidStateException: Attempt to set column "TORDERPOSTENTRY.ORDER_UID" to two different values: (null)"null", (class java.lang.Long)"117,801" This can occur when you fail to set both sides of a two-sided relation between objects, or when you map different fields to the same column, but you do not keep the values of these fields in synch."


The setXXX() method will be called by openjpa when it try to read data from database and populate them into java object. The code to set order automatically should not be called by the openjpa.

To make it work, another set method should be created and that will be used by openjpa internally.



        @OneToMany(mappedBy = "order", targetEntity = AbstractOrderPostEntryImpl.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
protected Set getOrderPostEntriesInternal() {
return this.orderPostEntries;
}

protected void setOrderPostEntriesInternal(final Set orderPostEntries) {
this.orderPostEntries = orderPostEntries;
}

@Transient
public Set getOrderPostEntries() {
return getOrderPostEntriesInternal();
}

public void setOrderPostEntries(final Set orderPostEntries) {
for (OrderPostEntry orderPostEntry : orderPostEntries) {
orderPostEntry.setOrder(this);
}
setOrderPostEntriesInternal(orderPostEntries);
}

The setOrderPostEntriesInternal method will be called by openjpa. The method setOrderPostEntries will be called when our code adds orderPostEntries into Order.

The code below on OrderPostEntry.java is not good. It may cause dead lock on database.



private long orderUid;

@Basic
@Column(name = "ORDER_UID")
public long getOrderUid() {
return this.orderUid;
}

public void setOrderUid(final long orderUid) {
this.orderUid = orderUid;
}

Thursday, September 24, 2009

Pagination on the object which is the “many” in a one-to-many relationship ?

Here is the scenario. We have objectA contains a list of objectB, a standard one-to-many relationship. But each objectA has millions objectB and we don’t want to load all of them each time we load the objectA. The UI need load one objectA and the first 100 objectB and has the pagination button to see previous/next 100 objectB records.

Can lazy load work for pagination?

What happens if only the properties of objectA are updated? when the object is updated on UI and sent back to dao to do the updating, objectA only contains 100 objectB, will the persistence engine delete all the other objectB?

related articles on internet

http://www.ilikespam.com/blog/paging-large-data-sets-with-a-lazylist




Monday, July 27, 2009

OpenJPA @Version on LAST_MODIFIED_DATE

Before, we put @Version on the LAST_MODIFIED_DATE and openjpa will automatically populate it with the current system time (from that JVM). It is ok in a simple environment.

But when our project is deployed in some enterprise environment, which has clustered application servers, each server may have different time or time zone. It is not good to populate the LAST_MODIFIED_DATE which is from each JVM.

The solution is that we added a listener for that domain object instead of @Version. The listener will be triggered before insert/update is happening.  The listener get the current time from a centralized time service server.

Thursday, July 16, 2009

OpenJpa Optimistic locking issue

In one of my project, the entity object is detached and sent to the rich client (eclipse rcp). Any operation on the client UI affects the detached object right away.  For example, there is a Boolean field on the entity object. The original value is true, and the user changes it to false on the UI. It changes the value in the object right away and the detached object is marked as “dirty”. But before the user save the change, he changes his mind and changes it back to true. But the detached object is still marked as “dirty”. When the object is going to be updated, openjpa finds that field is dirty and assumes that value is changed. Openjpa compares that value with the one in database and expect they are different but it gets the same value so that openjpa assumes some other transaction already changed the value in database and throws out the optimistic locking exception.

Friday, May 15, 2009

JPA: use of Map collections for OneToMany

Here is the tables

image

Data sample:

UIDPK GROUP_NAME CODE PARENT_PROPERTY_UID
1 “COUNTRY” CA NULL

 

UIDPK PROPERTY_UID VALUE LOCALE
1 1 CANADA en
2 1 KANTANA fr

The property value would be a collection in the object Property. We want to use Map here and the key will be “LOCALE”

public class PropertyImpl {
…    
@OneToMany(targetEntity = PropertyValueImpl.class, fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
    @MapKey(name = "locale")
@ElementJoinColumn(name = "PROPERTY_UID", nullable = false)
    public Map<String, PropertyValue> getPropertyValues() {
        return propertyValues;

    }    
public void setPropertyValues(Map<String, PropertyValue> propertyValues) {
        this.propertyValues = propertyValues;

    }

The “locale” in @MapKey should be one property name in PropertyValueImpl.class.

How to filter collection in JPA/JPQL?

I have two entities:

@Entity
public class Customer  implements java.io.Serializable {
...
    @OneToMany(fetch=FetchType.EAGER, mappedBy="customer")
    private Set<CustomerOrder> customerOrders;
...


@Entity
public class CustomerOrder  implements java.io.Serializable {
....       

    private double cost;

    @ManyToOne
    @JoinColumn(name="CUST_ID")
    public Customer customer;
...


Now in my JPQL, I want to return those customers with their CustomerOrder.cost>1000. For example, there are three customers A, B and C. A has two orders with cost=1000 and 2000 respectively. B has three orders with cost=2000,3000 and 500 respectively. C has one order with cost=500. Now i want to get the three customers: A returns the orders with cost=2000 only; B returns the orders with 2000 and 3000; C returns an empty orders collection.



But the following will always return the full collection:



select c from Customer c, in(c.customerOrders) o where o.cost>1000


How can I do that in JPQL or in Hibernate in particular?

JPA self join table

In my project, we have some properties which have a bunch of sub properties. For example

CA=Canada
    |—AB= Alberta
    |—BC= British Columbia
I generated a self join table tproperty.

image

Here is the entity.
public class PropertyImpl extends AbstractEntityImpl implements Property {     private long uidPk; 

    private String groupName;

    private String code;

    private Property parentProperty;

    private Set<Property> subProperties;

    private Collection<PropertyValue> propertyValues;    
@OneToMany(targetEntity = PropertyImpl.class, fetch = FetchType.EAGER, cascade = { CascadeType.ALL },
mappedBy = "parentProperty")

    public Set<Property> getSubProperties() {
        return subProperties;

    }    
public void setSubProperties(Set<Property> subProperties) {

        this.subProperties = subProperties;

        if (subProperties != null) {

            for (Property property : subProperties) {

                property.setParentProperty(this);

            }

        }

    }   

@ManyToOne(targetEntity = PropertyImpl.class)
@JoinColumn(name = "PARENT_PROPERTY_UID", nullable = true)


    public Property getParentProperty() {

        return parentProperty;

    }    
public void setParentProperty(Property parentProperty) {

        this.parentProperty = parentProperty;

    }

}

Tuesday, February 24, 2009

openjpa set SupportsSubSelect

<property name="openjpa.jdbc.DBDictionary" value="mysql(SupportsSubselect=true)"/>

My jpql is like this:
DELETE FROM ChangeSetImpl cs WHERE cs.objectGroupId = ?1 AND 
(NOT EXISTS(SELECT gm FROM BusinessObjectGroupMemberImpl gm WHERE gm.groupId = ?1))


I hope it could generate the sql like this:
DELETE FROM TCHANGESET 
WHERE OBJECT_GROUP_ID = '0B89B168-3D84-AC82-0A49-C1044499C467' AND NOT (EXISTS (SELECT
t1.UIDPK FROM TOBJECTGROUPMEMBER t1 WHERE t1.OBJECT_GROUP_ID = '0B89B168-3D84-AC82-0A49-C1044499C467')) ;


But openjpa generate a complicated sql which does not work on MySql. We may need wait for the next version of openjpa.
Here is the sql generated by openjpa.
DELETE FROM TCHANGESET 
WHERE UIDPK IN (SELECT DISTINCT t2.UIDPK FROM TCHANGESET t2 WHERE ((SELECT COUNT(t1.UIDPK) FROM TOBJECTGROUPMEMBER t0,
TOBJECTGROUPMEMBER t1 WHERE (t0.OBJECT_GROUP_ID = ?)) = ? AND t2.OBJECT_GROUP_ID = ?))

Wednesday, February 11, 2009

openJPA Enhance, Mapping and Reverse Mapping Tool

Enhance
java org.apache.openjpa.enhance.PCEnhancer


Mapping Tool: generate tables based on the entity classes and the annotations on them.
java org.apache.openjpa.jdbc.meta.MappingTool


Reverse Mapping Tool: generate the entity classes based on the tables from database
java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg example.openjpa.reverse -d src/main/java -annotations true

Monday, February 9, 2009

OpenJPA Caching

The JPA specification defines two levels of caching: one that is scoped to the Entity Manager and another that is scoped to the Persistent Unit. The Entity Manager level cache is associated with a current transaction unless you are using the Extended Context—in which you can scope the cache to the life cycle of a Stateful Session Bean. We discussed this life cycle earlier in the "Programming Model" section. The JPA Entity Manager has a flush method you can invoke to clear the cache and push changes to the database.

The Entity Manager cache is there is for keeping data around during a multi-request flow, often called a "conversation;" however, the persistence unit cache is meant to really be a performance booster for read-only or read-mostly data. OpenJPA provides a data-level cache at the persistence unit level. OpenJPA provides a Single JVM cache provider. This may be ideal for read-only data that is initialized during the startup of an application.

For Example:
<property name="openjpa.DataCache" value="true(CacheSize=5000, SoftReferenceSize=0)"/>
<property name="openjpa.QueryCache" value="CacheSize=1000, SoftReferenceSize=100"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm"/>


"svjm" here means "single jvm". Is there any other option here? How to use caching in distributed environment?

JPA field access vs property access

Here are the two examples of field access and property access.
Field access
@ManyToOne
private Company publisher;


Property Access
@ManyToOne
private Company getPublisher() { ... }


When using property access, only the getter and setter method for a property should ever access the underlying persistent field directly. Other methods, including internal business methods in the persistent class, should go through the getter and setter methods when manipulating persistent state.
Also, take care when adding business logic to your getter and setter methods. Consider that they are invoked by the persistence implementation to load and retrieve all persistent state; other side effects might not be desirable.

Each class must use either field access or property access for all state; you cannot use both access types within the same class.
Additionally, a subclass must use the same access type as its superclass.