OneToMany Create Fails with InvalidDataAccessApiUsageException - spring

I am fairly new to Hibernate and have been using the manual & online forums, but I am stumped on this issue. I’m using Spring 3.2 with Hibernate 4 & Annotations. I have a parent (PledgeForm) & child (PledgeFormGiftLevel) table that is one-to-many.
Domain/Models:
Parent
#Entity
#Table(name="PLEDGE_FORMS")
#SuppressWarnings("serial")
public class PledgeForm implements Serializable {
static final Logger log = Logger.getLogger(PledgeForm.class);
#Id
#GeneratedValue(strategy=GenerationType.AUTO, generator="pledge_form_seq")
#SequenceGenerator(name="pledge_form_seq", sequenceName="PLEDGE_FORM_SEQ")
#Column(name="ID", unique=true, nullable=false)
private Integer id;
….
#OneToMany(mappedBy="pledgeForm", fetch=FetchType.EAGER, cascade=CascadeType.ALL)//********1
private List<PledgeFormGiftLevel> pledgeFormGiftLevels = new ArrayList<PledgeFormGiftLevel>();
….
public List<PledgeFormGiftLevel> getPledgeFormGiftLevels() {
return this.pledgeFormGiftLevels;
}
public void setPledgeFormGiftLevels(List<PledgeFormGiftLevel> pledgeFormGiftLevels) {
this.pledgeFormGiftLevels = pledgeFormGiftLevels;
}
//I do not think the following method is needed, but I decided to try it just in case
public void addPledgeFormGiftLevels(PledgeFormGiftLevel pledgeFormGiftLevels) {
pledgeFormGiftLevels.setPledgeForm(this);
getPledgeFormGiftLevels().add(pledgeFormGiftLevels);
}
Child
#Entity
#Table(name="PLEDGE_FORM_GIFT_LEVELS")
#SequenceGenerator(name="pledge_form_gift_level_seq", sequenceName="PLEDGE_FORM_GIFT_LEVEL_SEQ")
#SuppressWarnings("serial")
public class PledgeFormGiftLevel implements Serializable {
static final Logger log = Logger.getLogger(PledgeFormGiftLevel.class);
#Id
#GeneratedValue(strategy=GenerationType.AUTO, generator="pledge_form_gift_level_seq")
#Column(name="ID", unique=true, nullable=false)
private Integer id;
…
#ManyToOne(fetch=FetchType.EAGER)//yes?
#JoinColumn(name="PLEDGE_FORM_ID", referencedColumnName="ID", insertable=true, updatable=true)//yes?
private PledgeForm pledgeForm = new PledgeForm();
…
public PledgeForm getPledgeForm() {
return pledgeForm;
}
public void setPledgeForm(PledgeForm pledgeForm) {
this.pledgeForm = pledgeForm;
}
Controller (there is a graphic, so I have code to pull in the file):
#Controller
#SessionAttributes("pledgeForm")
public class PledgeFormController {
#Autowired
org.unctv.service.PledgeFormManager Service;
…
#RequestMapping(value = "/saveJdbcPledgeForm", method = RequestMethod.POST, params="save")
public ModelAndView save(
#ModelAttribute("pledgeForm")
#Valid PledgeForm pledgeForm, BindingResult result,
#RequestParam("logoImg") MultipartFile file,
#RequestParam(value="removeLogoImg", required=false) String removeLogoImg) throws Exception {
ModelAndView mav = null;
mav = new ModelAndView("pledgeFormSearch");//Name of the JSP
if (removeLogoImg != null) {
pledgeForm.setLogoFilename(null);
pledgeForm.setLogoImg(null);
pledgeForm.setLogoContentType(null);
} else if (file != null && file.getBytes().length > 0) {
pledgeForm.setLogoFilename(file.getOriginalFilename());
pledgeForm.setLogoImg(file.getBytes());
pledgeForm.setLogoContentType(file.getContentType());
}
Service.save(pledgeForm);
mav.addObject("pledgeForm", pledgeForm);//JSP Form's Command Name (pledgeForm);
mav.addObject("cmdName", "pledgeForm");
mav.addObject("actionType", "Save");
return mav;
}
Service:
#Service("simplePledgeFormManager")
#Transactional(readOnly=true)
public class SimplePledgeFormManager implements PledgeFormManager {
#Autowired
private HibernatePledgeFormDao hibernatePledgeFormDao;
…
#Transactional(readOnly=false)
public void save(PledgeForm pledgeForm) throws Exception {
hibernatePledgeFormDao.save(pledgeForm);
}
DAO:
#Repository("PledgeFormDAO")
public class HibernatePledgeFormDao implements PledgeFormDao {
static final Logger log = Logger.getLogger(HibernatePledgeFormDao.class);
#Autowired
private SessionFactory sessionFactory;
...
#Override
public void save(PledgeForm pledgeForm) throws Exception {
sessionFactory.getCurrentSession().saveOrUpdate(pledgeForm);
}
Using the code above, parent/child records can be selected and updated fine. When I display the “trace” messages from hibernate, the update does have this trace message about the child, though:
[2013-12-06 10:31:24,648] TRACE Persistent instance of: org.unctv.domainmodel.PledgeFormGiftLevel
[2013-12-06 10:31:24,649] TRACE Ignoring persistent instance
[2013-12-06 10:31:24,649] TRACE Object already associated with session: [org.unctv.domainmodel.PledgeFormGiftLevel#1]
The create always gives this error if there is a child record:
object references an unsaved transient instance - save the transient instance before flushing: org.unctv.domainmodel.PledgeForm; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: org.unctv.domainmodel.PledgeForm
When I look at the hibernate logs, I see that it updates the parent & the child based on transient objects. Then it tries to flush & finds a persistent copy of the child, so it rolls back everything.
[2013-12-06 10:34:13,615] TRACE Automatically flushing session
[2013-12-06 10:34:13,615] TRACE Flushing session
[2013-12-06 10:34:13,615] DEBUG Processing flush-time cascades
[2013-12-06 10:34:13,615] TRACE Processing cascade ACTION_SAVE_UPDATE for: org.unctv.domainmodel.PledgeForm
[2013-12-06 10:34:13,615] TRACE Cascade ACTION_SAVE_UPDATE for collection: org.unctv.domainmodel.PledgeForm.pledgeFormGiftLevels
[2013-12-06 10:34:13,615] TRACE Cascading to save or update: org.unctv.domainmodel.PledgeFormGiftLevel
[2013-12-06 10:34:13,616] TRACE Persistent instance of: org.unctv.domainmodel.PledgeFormGiftLevel
[2013-12-06 10:34:13,616] TRACE Ignoring persistent instance
[2013-12-06 10:34:13,616] TRACE Object already associated with session: [org.unctv.domainmodel.PledgeFormGiftLevel#51]
[2013-12-06 10:34:13,616] TRACE Done cascade ACTION_SAVE_UPDATE for collection: org.unctv.domainmodel.PledgeForm.pledgeFormGiftLevels
[2013-12-06 10:34:13,616] TRACE Done processing cascade ACTION_SAVE_UPDATE for: org.unctv.domainmodel.PledgeForm
[2013-12-06 10:34:13,617] DEBUG Dirty checking collections
[2013-12-06 10:34:13,617] TRACE Flushing entities and processing referenced collections
[2013-12-06 10:34:13,617] DEBUG Collection found: [org.unctv.domainmodel.PledgeForm.pledgeFormGiftLevels#51], was: [<unreferenced>] (initialized)
[2013-12-06 10:34:13,618] DEBUG rolling back
[2013-12-06 10:34:13,618] DEBUG rolled JDBC Connection
The Hibernate documentation shows this as even simpler than I my code is, but I had to add the fetch & cascade values. I’ve played with changing the fetch & cascade values & placement (starting with the Hibernate documentation & then adding on), but everything else I try still causes the create to fail & often causes the update to fail too.
Many forum posts that I find show flush() or evict(). I am not certain if it is Hibernate 4 or annotations (#Transactional, I think) I’m using, but I do not see a place for that in my code. From the Hibernate trace logs, I can see that flushing is occurring automatically with in the saveOrUpdate() method.
I also tried dropping the tables & sequences & starting fresh.
Any advice about getting the create to work is appreciated. If you can point me to specific documentation that I missed, that is appreciated as well.
Thanks,
Bonnie

I noticed that equals and hashcode have not been overridden in the entities. These methods are used to compare objects to determine their equality. Hibernate may not be able to determine if an existing instance of the entity exists without these methods being overridden. Try providing implementations for hashcode and equals.
If your using Eclipse, press CTRL + SHIFT + S, H to bring up the dialog for creating the hashcode and equals methods. Pick fields that contain values that are relatively unchanged and then generate the methods.
Also be sure that you are managing both sides of the entity as discussed in the above comments:
public ModelAndView save(
#ModelAttribute("pledgeForm")
#Valid PledgeForm pledgeForm, BindingResult result,
#RequestParam("logoImg") MultipartFile file,
#RequestParam(value="removeLogoImg", required=false) String removeLogoImg) throws Exception {
ModelAndView mav = null;
mav = new ModelAndView("pledgeFormSearch");//Name of the JSP
//Manage both sides of the entity
List<PledgeFormGiftLevel> levels = pledgeForm.getPledgeFormGiftLevels();
for(PledgeFormGiftLevel level: levels){
level.setPledgeForm(pledgeForm);
}
if (removeLogoImg != null) {
pledgeForm.setLogoFilename(null);
pledgeForm.setLogoImg(null);
pledgeForm.setLogoContentType(null);
} else if (file != null && file.getBytes().length > 0) {
pledgeForm.setLogoFilename(file.getOriginalFilename());
pledgeForm.setLogoImg(file.getBytes());
pledgeForm.setLogoContentType(file.getContentType());
}
Service.save(pledgeForm);
mav.addObject("pledgeForm", pledgeForm);//JSP Form's Command Name (pledgeForm);
mav.addObject("cmdName", "pledgeForm");
mav.addObject("actionType", "Save");
return mav;
}

Related

Spring Data JpaRepository throws LazyInitializationException when using method getById() but not when using findById()

in my Spring Boot (version 2.5.4) I have a service that executes one of its methods by a ExecutorService (in new Thread). in this new Thread I access some of my repositories (JpaRepositorys). I see different behavior in JpaRepository's getById() and findById(), I searched but did not found any.
this is my entity:
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
public class LimoSet {
#Id
#Column(name = "_id")
private String id;
#Column(name = "_status")
private String status;
#OneToMany(mappedBy = "set", fetch = FetchType.EAGER)
private Set<Limo> limos = new LinkedHashSet<>();
#Column(name = "_statistics")
private String statistics;
}
this is repository:
#Repository
public interface LimoSetRepository extends JpaRepository<LimoSet, String> {
}
and this is the service:
#Service
#Transactional
public class GeneratorService {
private final static Logger logger = LoggerFactory.getLogger(GeneratorService.class);
private final LimoSetRepository setRepository;
private final ExecutorService executor = Executors.newFixedThreadPool(3);;
public void generate(Options opts) {
.
.
.
Callable<String> task = () -> {
try {
this.runGenerate(opts);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
var set = setRepository.getById(opts.getName());
set.setStatus(e.getMessage());
setRepository.save(set);
}
return "ok";
};
executor.submit(task);
}
void runGenerate(Options opts) throws JsonProcessingException {
.
.
.
var set = setRepository.findById(opts.getName()).get(); //this is ok
var set = setRepository.getById(opts.getName()); //this throws LazyInitializationException
set.setStatus("GENERATED"); //the Exception is reported in this line
setRepository.save(set);
}
}
why findById() works but getById() does not?
There are a few factors which sum up to the LazyInitializationException.
For primers:
get acquainted with the different semantics of findById and getById
findById fetches entire object
getById fetches object proxy
See: How do find and getReference EntityManager methods work when using JPA and Hibernate
When loading a Proxy, you need to be aware that a LazyInitializationException can be thrown if you try to access the Proxy reference after the EntityManager is closed.
Secondly, you need to understand why runGenerate runs with no active transaction, even if the class is marked as #Transactional.
(Note: no active transaction is the root cause of closed EntityManager)
To make sure that the transaction is not active, see Detecting If a Spring Transaction Is Active:
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
Why parent transaction from the test is not propagated
runGenerate is run via executor on a separate thread
active transaction is kept as a thread-local, so transactions do not propagate across threads.
Why #Transactional on runGenerate has no effect?
Spring (by default) uses CGLIB proxies to enable aspects.
CGLIB proxies has 2 requirements:
the proxied method must be public
you must call the method via the proxy (not via the actual object)
None of these conditions is met.
Why the transaction is active in the test itself
Spring provides a special TestExecutionListener called TransactionalTestExecutionListener, which checks if the test method is marked as #Transactional, and starts transaction if needed
How to fix
extract runGenerate to a service, mark it as public and #Transactional
autowire the new service into your test
more generally, take note what parts of your task operate under transactional context (catch block of your task is not transactional)
also more generally, learn about dirty checking. once you have your methods to run under transactional context, the save calls will be redundant.

CRUDRepository unable to save modified entities

I'm trying to fetch some data from the database, update a field with some other entity and save it back to the DB, of course I've made sure that both the first entity and the entity that is going to be inserted are retrieved and fine, it is just thrown upon the save function invokation.
Here's the exception
[err] org.springframework.dao.DataIntegrityViolationException: Attempt to persist detached object "repository.entities.RequestEntity-0". If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.; nested exception is <openjpa-2.4.3-r422266:1833086 nonfatal store error> org.apache.openjpa.persistence.EntityExistsException: Attempt to persist detached object "repository.entities.RequestEntity-0". If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.
FailedObject: repository.entities.RequestEntity-0
The entity
#Entity
#Table(name="REQUEST")
public class RequestEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="REQUEST_ID")
private long requestId;
some other fields ....
//bi-directional many-to-one association to MStatus
#ManyToOne
#JoinColumn(name="STATUS")
private MStatus mStatus;
getters and setters here as well ..
}
And lastly, here's the code
private void doStuff() throws Exception {
List<RequestEntity> requestsList = requestRepo
.findByMStatusStatusContaining("TEXT");
RequestEntity requestItem;
if (requestsList.size() > 1 || requestsList.isEmpty()) {
throw new Exception("No requests found");
} else {
requestItem = requestsList.get(0);
}
requestItem.setMApprovalStatus(mapprovalStatus.findOne("TEXT_TWO"));
requestRepo.save(requestItem);
}

Saving Entity with Cached object in it causing Detached Entity Exception

I'm trying to save an Entity in DB using Spring Data/Crud Repository(.save) that has in it another entity that was loaded through a #Cache method. In other words, I am trying to save an Ad Entity that has Attributes entities in it, and those attributes were loaded using Spring #Cache.
Because of that, I'm having a Detached Entity Passed to Persist Exception.
My question is, is there a way to save the entity still using #Cache for the Attributes?
I looked that up but couldn't find any people doing the same, specially knowing that I am using CrudRepository that has only the method .save(), that as far as I know manages Persist, Update, Merge, etc.
Any help is very much appreciated.
Thanks in advance.
Ad.java
#Entity
#DynamicInsert
#DynamicUpdate
#Table(name = "ad")
public class Ad implements SearchableAdDefinition {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private User user;
#OneToMany(mappedBy = "ad", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<AdAttribute> adAttributes;
(.....) }
AdAttribute.java
#Entity
#Table(name = "attrib_ad")
#IdClass(CompositeAdAttributePk.class)
public class AdAttribute {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ad_id")
private Ad ad;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "attrib_id")
private Attribute attribute;
#Column(name = "value", length = 75)
private String value;
public Ad getAd() {
return ad;
}
public void setAd(Ad ad) {
this.ad = ad;
}
public Attribute getAttribute() {
return attribute;
}
public void setAttribute(Attribute attribute) {
this.attribute = attribute;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
#Embeddable
class CompositeAdAttributePk implements Serializable {
private Ad ad;
private Attribute attribute;
public CompositeAdAttributePk() {
}
public CompositeAdAttributePk(Ad ad, Attribute attribute) {
this.ad = ad;
this.attribute = attribute;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CompositeAdAttributePk compositeAdAttributePk = (CompositeAdAttributePk) o;
return ad.getId().equals(compositeAdAttributePk.ad.getId()) && attribute.getId().equals(compositeAdAttributePk.attribute.getId());
}
#Override
public int hashCode() {
return Objects.hash(ad.getId(), attribute.getId());
}
}
Method using to load Attributes:
#Cacheable(value = "requiredAttributePerCategory", key = "#category.id")
public List<CategoryAttribute> findRequiredCategoryAttributesByCategory(Category category) {
return categoryAttributeRepository.findCategoryAttributesByCategoryAndAttribute_Required(category, 1);
}
Method used to create/persist the Ad:
#Transactional
public Ad create(String title, User user, Category category, AdStatus status, String description, String url, Double price, AdPriceType priceType, Integer photoCount, Double minimumBid, Integer options, Importer importer, Set<AdAttribute> adAtributes) {
//Assert.notNull(title, "Ad title must not be null");
Ad ad = adCreationService.createAd(title, user, category, status, description, url, price, priceType, photoCount, minimumBid, options, importer, adAtributes);
for (AdAttribute adAttribute : ad.getAdAttributes()) {
adAttribute.setAd(ad);
/* If I add this here, I don't face any exception, but then I don't take benefit from using cache:
Attribute attribute = attributeRepository.findById(adAttribute.getAttribute().getId()).get();
adAttribute.setAttribute(attribute);
*/
}
ad = adRepository.save(ad);
solrAdDocumentRepository.save(AdDocument.adDocumentBuilder(ad));
return ad;
}
I don't know if you still require this answer or not, since it's a long time, you asked this question. Yet i am going to leave my comments here, someone else might get help from it.
Lets assume, You called your findRequiredCategoryAttributesByCategory method, from other part of your application. Spring will first check at cache, and will find nothing. Then it will try to fetch it from Database. So it will create an hibernate session, open a transaction, fetch the data, close the transaction and session. Finally after returning from the function, it will store the result set in cache for future use.
You have to keep in mind, those values, currently in the cache, they are fetched using a hibernate session, which is now closed. So they are not related to any session, and now at detached state.
Now, you are trying to save and Ad entity. For this, spring created a new hibernate session, and Ad entity is attached to this particular session. But the attributes object, that you fetched from the Cache are detached. That's why, while you are trying to persist Ad entity, you are getting Detached Entity Exception
To resolve this issue, you need to re attach those objects to current hibernate session.I use merge() method to do so.
From hibernate documentation here https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".
Simply put, this will attach your object to hibernate session.
What you should do, after calling your findRequiredCategoryAttributesByCategory method, write something like
List attributesFromCache = someService.findRequiredCategoryAttributesByCategory();
List attributesAttached = entityManager.merge( attributesFromCache );
Now set attributesAttached to your Ad object. This won't throw exception as attributes list is now part of current Hibernate session.

JPA Hibernate Spring Repository ensures transaction completes on save?

I am creating a simple spring application which is supposed to book seats in a seminar. Lets say Booking class looks like this
#Entity
#Table(name = "bookings")
#IdClass(BookingId.class)
public class Booking{
#Id
private Long seminarId;
#Id
private String seatNo;
// .. other fields like perticipant info
// .. getter setters
}
of course the BookingId class:
public class BookingId implements Serializable{
private static final long serialVersionUID = 1L;
private Long seminarId;
private String seatNo;
// .. constructors, getters, setters
}
And I have a repository
#Repository
public interface BookingsRepository extends JpaRepository<Booking, BookingId>{
}
in the controller when a booking request arrives I first check if a booking with same seminer id and seat number already exists, if it doesn't exist I create one
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<BaseCrudResponse> createNewBooking(#Valid #RequestBody NewBookingDao newBookingDao, BindingResult bindingResult){
logger.debug("Request for a new booking");
// .. some other stuffs
Booking newBooking = new Booking();
newBooking.setSeminarId(newBookingDao.getSeminarId());
newBooking.setSeatNumber(newBookingDao.getSeatNumber());
// .. set other fields
Booking existing = bookingsRepository.findOne(new BookingId(newBooking.getSeminarId(), newBooking.getSeatNumber());
if (existing == null)
bookingsRepository.save(newBooking);
return new ResponseEntity<>(new BaseCrudResponse(0), HttpStatus.CREATED);
}
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
Now what will happen if the save method of the repository didn't finish commiting transaction and another request already gets past the existence check ? There might be incorrect booking (the last commit will override the previous). Is this scenario likely to happen ? Will the repository ensures that it completes the transaction before another save call ?
Also is there any way to tell Jpa to throw some exception (for IntegrityConstraintException if the composite key (in this case seminerId and seatNumber) already exists ? Now in the present setting its just updating the row.
You can use javax.persistence.LockModeType.PESSIMISTIC_WRITE so other transactions except the one that got the lock cannot update the entity.
If you use spring-data > 1.6 you can annotate the repository method with #Lock :
interface BookingsRepository extends Repository<Booking, Long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
Booking findOne(Long id);
}
For sure you need to handle the locking exception that may be thron in the controller.

OptimisticLockException not thrown when version has changed

I've created a simple EJB application that uses JPA for persistence and have a problem whereby optimistic locking is not functioning as I would have expected.
The application contains a class named Site which defines the model for a table named SITE in the database. The SITE table contains a column named ROW_VERSION which is referenced in the Site class using the #version annotation.
Whenever the record is updated, the ROW_VERSION is incremented by 1. So far, so good.
The problem arises when the row has changed in the time between the application reading the row using the EntityManager find method and the row being updated by the EntityManager merge method. As the ROW_VERSION for the row has been incremented by 1 and therefore is not the same as when the EntityManager find method was called, I would expect an OptimisticLockException to be thrown, but instead the changes are written to the table and in turn overwriting the changes made by the other process.
The application is running on WebSphere 8.5 and is using OpenJPA provided by the container.
Have I mis-understood how optimistic locking is supposed to work or is there something else that I need to do to make the OptimisticLockException occur?
The Site class is as follows:
#Entity
#Table(name="SITE")
public class Site {
#Id
#Column(name="SITE_ID")
private int id;
#Column(name="SITE_NAME")
private String siteName;
#Column(name="SITE_ADDRESS")
private String address;
#Column(name="ROW_VERSION")
#Version
private long rowVersion;
//getters and setters
}
The application makes uses of the Generic DAO wrapper class to invoke the EntityManager methods. The contents of the class are as follows:
public abstract class GenericDAO<T> {
private final static String UNIT_NAME = "Test4EJB";
#PersistenceContext(unitName = UNIT_NAME)
private EntityManager em;
private Class<T> entityClass;
public GenericDAO(Class<T> entityClass) {
this.entityClass = entityClass;
}
public T update(T entity) {
return em.merge(entity);
}
public T find(int entityID) {
return em.find(entityClass, entityID);
}
//other methods
}
Update - I've done some more investigation and have found this http://pic.dhe.ibm.com/infocenter/wasinfo/v8r0/index.jsp?topic=%2Fcom.ibm.websphere.nd.multiplatform.doc%2Finfo%2Fae%2Fae%2Fcejb_genversionID.html but even when I've added the #VersionColumn and #VersionStrategy annotations I still cannot get the OptimisticLockException to be thrown.

Resources