Monthly Archives: December 2012

Persisting a detached entity in JPA


In a JPA many to many relationship, if cascade type has been set at CascadeType.PERSIST (or CascadeType.ALL, which includes CascadeType.PERSIST), then while saving the parent and updating it with references of the child, it will try to save the child again.

	@ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch = FetchType.EAGER)
	@JoinTable(name="QP_Q", 
	joinColumns={@JoinColumn(name="questionpaperid")}, inverseJoinColumns=@JoinColumn(name="questionid"))

Following issues can appear

  1. Child is already in persistence store (A detached instance has been passed) -in this case it will throw an exception “org.hibernate.PersistentObjectException: detached entity passed to persist”
  2. Child is a new entry, then it will be added in its table and operation will complete successfully

Following are some solutions

  1. If requirement is that Parent should add a existing but detached child(creating an instance with same ID and passing on from the client) -it needs to be reattached to session first. Hmm -for this there is NO way in JPA -Nope, merge does not reattach and entity. If you are using hibernate, you are lucky, merge can do the trick
    For JPA, best option would be to query for entity on server side before trying to save it.
  2. If its sure that only new child will be added, and not an detached instance from DB, CascadeType.PERSIST will take care of
  3. On the other hand, if requirement is never to add a new child if its not alredy in DB then CascadeType.PERSIST should be removed and cascade={CascadeType.MERGE,CascadeType.REFRESH} should be used
	@ManyToMany(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch = FetchType.EAGER)
	@JoinTable(name="QP_Q", 
	joinColumns={@JoinColumn(name="questionpaperid")}, inverseJoinColumns=@JoinColumn(name="questionid"))

Fetching Nested collections in JPA


While coding in JPA with hibernate underneath I got an exception org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags. I was using “LIST” for the association and fetching eagerly

	@ManyToMany(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch = FetchType.EAGER)
	@JoinTable(name="class_subject", 
	joinColumns={@JoinColumn(name="classid")}, inverseJoinColumns=@JoinColumn(name="subjectid"))
	private List<SubjectDetails> subjects;

The problem seems to be two fold:

  1. JPA allows only two level of nesting for collection, Parententity->Childentity is fine but it does not allow Parententity->childentity->SubChildEntity
  2. Using List for collection instead of SET -remember a SET guarantees unique elements while list does not

What could be solution:

  1. Use SET instead of List and thats what I have done for the moment
	private SET<SubjectDetails> subjects;

  • Hibernate does allow, so we can use specific annotation but it will defy the whole purpose of using JPA
  • Review the model, instead of depending on Object graph to be fetched “Automagically” by ORM, can we move the logic in service layer and do the population as on need basis for required UI? And if you say it would throw lazy initialization because you have used session at DAO -Red Flag -its an anti pattern
  • Setting timeout for REST and SOAP webservices in Spring


    I got in a situation where one of the external providers were missing their SLA and instead of their agreed 3 sec (hypothetical) for response, webservice was taking ~1 minute.
    In this situation, the component was taking a lot of time to load -slowing down the whole page response. Following are the way to set the timeout parameter:

    • Setting JVM parameter (This will work ONLY for RESTfull services -Basically services dependent on JDK HTTP client)
      1. -Dsun.net.client.defaultConnectTimeout=1000 (Time to establish connection in millisec)
      2. -Dsun.net.client.defaultReadTimeout=1000 (Time to read content in millisec)

    This works because Spring template by default uses HTTPClient from JDK, if the factory class has been overridden to non JDK class it will fail

  • Injecting the parameters for REST template
  • 	<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    		<constructor-arg>
        		<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
        			<property name="readTimeout" value="100" />
        			<property name="connectTimeout" value="100"/>
       		 	</bean>
    		</constructor-arg>
    	</bean>   
    

    Be sure not to use the depricated class “org.springframework.http.client.CommonsClientHttpRequestFactory”, otherwise it throws an error while setting connectTimeout

  • Injecting the parameters for SOAP Service
  •         <property name="messageSender">
                <bean
                    class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
                         <property name="connectionTimeout" value="10" />
                  <property name="readTimeout" value="100" />
                </bean>
            </property>