SharedEntityManagerCreator immediately throws TransactionRequiredException on persist, merge, remove etc (as required by JPA spec)
Issue: SPR-11923
This commit is contained in:
@@ -23,10 +23,13 @@ import java.lang.reflect.InvocationHandler;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TransactionRequiredException;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -61,6 +64,23 @@ public abstract class SharedEntityManagerCreator {
|
|||||||
|
|
||||||
private static final Class<?>[] NO_ENTITY_MANAGER_INTERFACES = new Class<?>[0];
|
private static final Class<?>[] NO_ENTITY_MANAGER_INTERFACES = new Class<?>[0];
|
||||||
|
|
||||||
|
private static final Set<String> transactionRequiringMethods = new HashSet<String>(6);
|
||||||
|
|
||||||
|
private static final Set<String> queryTerminationMethods = new HashSet<String>(3);
|
||||||
|
|
||||||
|
static {
|
||||||
|
transactionRequiringMethods.add("joinTransaction");
|
||||||
|
transactionRequiringMethods.add("flush");
|
||||||
|
transactionRequiringMethods.add("persist");
|
||||||
|
transactionRequiringMethods.add("merge");
|
||||||
|
transactionRequiringMethods.add("remove");
|
||||||
|
transactionRequiringMethods.add("refresh");
|
||||||
|
|
||||||
|
queryTerminationMethods.add("getResultList");
|
||||||
|
queryTerminationMethods.add("getSingleResult");
|
||||||
|
queryTerminationMethods.add("executeUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
* Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
||||||
@@ -246,6 +266,13 @@ public abstract class SharedEntityManagerCreator {
|
|||||||
}
|
}
|
||||||
// Still perform unwrap call on target EntityManager.
|
// Still perform unwrap call on target EntityManager.
|
||||||
}
|
}
|
||||||
|
else if (transactionRequiringMethods.contains(method.getName())) {
|
||||||
|
// We need a transactional target now, according to the JPA spec.
|
||||||
|
// Otherwise, the operation would get accepted but remain unflushed...
|
||||||
|
if (target == null) {
|
||||||
|
throw new TransactionRequiredException("No transactional EntityManager available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Regular EntityManager operations.
|
// Regular EntityManager operations.
|
||||||
boolean isNewEm = false;
|
boolean isNewEm = false;
|
||||||
@@ -337,8 +364,7 @@ public abstract class SharedEntityManagerCreator {
|
|||||||
throw ex.getTargetException();
|
throw ex.getTargetException();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (method.getName().equals("getResultList") || method.getName().equals("getSingleResult") ||
|
if (queryTerminationMethods.contains(method.getName())) {
|
||||||
method.getName().equals("executeUpdate")) {
|
|
||||||
// Actual execution of the query: close the EntityManager right
|
// Actual execution of the query: close the EntityManager right
|
||||||
// afterwards, since that was the only reason we kept it open.
|
// afterwards, since that was the only reason we kept it open.
|
||||||
EntityManagerFactoryUtils.closeEntityManager(this.em);
|
EntityManagerFactoryUtils.closeEntityManager(this.em);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.orm.jpa;
|
package org.springframework.orm.jpa;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.TransactionRequiredException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -40,4 +42,46 @@ public class SharedEntityManagerCreatorTests {
|
|||||||
is(notNullValue()));
|
is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnJoinTransaction() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.joinTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnFlush() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnPersist() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.persist(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnMerge() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.merge(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnRemove() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.remove(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
public void transactionRequiredExceptionOnRefresh() {
|
||||||
|
EntityManagerFactory emf = mock(EntityManagerFactory.class);
|
||||||
|
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
|
||||||
|
em.refresh(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user