Java EE JTA 从不事务
Posted
技术标签:
【中文标题】Java EE JTA 从不事务【英文标题】:Java EE JTA Never Transaction 【发布时间】:2018-10-30 20:49:01 【问题描述】:我正在了解 JTA 事务并正在做 Junit。我遵循了来自 TomEE 示例的示例代码。为了更好地理解服务类,我做了一些更改。
我有 2 个测试用例。 1. 有交易 2. 没有交易
第一个测试用例运行良好。但第二个不是。因为第二种方法以从不启动事务属性。但是服务类的所有方法都需要 TA(事务属性)。删除事务未提交,因为我的测试用例失败。
为什么删除事务没有提交? (即使 delete 方法有 REQUIRED TA )
那么添加事务是如何工作的? (从 GetMovies 方法获取电影)
实体 @实体 公共类电影
@Id
private long movieId;
private String title;
private String director;
private int year;
public Movie()
public Movie(String director, String title, int year, long id)
this.director = director;
this.title = title;
this.year = year;
this.movieId = id;
public String getDirector()
return director;
public void setDirector(String director)
this.director = director;
public String getTitle()
return title;
public long getMovieId()
return movieId;
public void setTitle(String title)
this.title = title;
public int getYear()
return year;
public void setYear(int year)
this.year = year;
服务类
package com.demo.ex.service;
import com.demo.ex.entity.Movie;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.List;
@Stateless
public class MovieService
@PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public void addMovie(Movie movie)
System.out.println(" Add Movie "+movie.getTitle() +" "+movie.getMovieId());
em.persist(movie);
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public void deleteMovie(Movie movie)
em.remove(movie);
System.out.println(" Delete Movie "+movie.getTitle()+" "+movie.getMovieId());
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public List<Movie> getMovies()throws Exception
System.out.println(" Get Movie ");
return em.createQuery("select m from Movie as m").getResultList();
测试类
package com.demo.ex;
import com.demo.ex.entity.Movie;
import com.demo.ex.service.MovieService;
import junit.framework.TestCase;
import javax.ejb.*;
import javax.ejb.embeddable.EJBContainer;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
public class MovieTest extends TestCase
@EJB
private MovieService movieService;
@EJB(beanName = "TestTransaction")
private Caller transactionCaller;
@EJB(beanName = "TestNoTransaction")
private Caller noTransactionCaller;
protected void setUp() throws Exception
final Properties p = new Properties();
p.put("movieDatabase", "new://Resource?type=DataSource");
p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
EJBContainer.createEJBContainer(p).getContext().bind("inject", this);
@Override
protected void tearDown() throws Exception
transactionCaller.call(new Callable<Object>()
@Override
public Object call() throws Exception
System.out.println(" Tear Down Action.................");
for (final Movie m : movieService.getMovies())
System.out.println(" Teardown delete :"+m);
movieService.deleteMovie(m);
System.out.println("After cleanup movie count="+movieService.getMovies().size());
return null;
);
private void doWork() throws Exception
movieService.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992,1));
movieService.addMovie(new Movie("Joel Coen", "Fargo", 1996,2));
movieService.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998,3));
List<Movie> list = movieService.getMovies();
System.out.println(" Movie Serivce List :::"+list.size());
assertEquals("List.size()", 3, list.size());
for (Movie movie : list)
movieService.deleteMovie(movie);
System.out.println(" ???????????????????? SIZE:"+movieService.getMovies().size());
assertEquals("Movies.getMovies()", 0, movieService.getMovies().size());
public void testWithTransaction() throws Exception
transactionCaller.call(() ->
doWork();
return null;
);
public void testWithoutTransaction() throws Exception
try
noTransactionCaller.call(() ->
doWork();
return null;
);
catch (EJBException e)
e.printStackTrace();
public static interface Caller
public <V> V call(Callable<V> callable) throws Exception;
@Stateless
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public static class TestTransaction implements Caller
@Override
public <V> V call(Callable<V> callable) throws Exception
return callable.call();
@Stateless
@TransactionAttribute(value = TransactionAttributeType.NEVER)
public static class TestNoTransaction implements Caller
@Override
public <V> V call(Callable<V> callable) throws Exception
return callable.call();
Persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="movie-unit">
<jta-data-source>movieDatabase</jta-data-source>
<non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
<class>com.demo.ex.entity.Movie</class>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
<property name="openjpa.Log" value="SQL=TRACE" />
<property name="openjpa.ConnectionFactoryProperties"
value="printParameters=true"/>
</properties>
</persistence-unit>
</persistence>
【问题讨论】:
【参考方案1】:从非事务性上下文调用:您正在对分离的实例进行 remove。但是您在另一个事务中创建了实体 movie。因此,首先您需要进行合并,使其成为托管实体。
managedMovie = em.merge(movie);
em.remove(managedMovie);
参见 Javadoc:
IllegalArgumentException - 如果实例不是实体或分离实体
【讨论】:
以上是关于Java EE JTA 从不事务的主要内容,如果未能解决你的问题,请参考以下文章