Java EE JTA Никогда Транзакция - PullRequest
       82

Java EE JTA Никогда Транзакция

0 голосов
/ 30 октября 2018

Я понимаю транзакцию JTA и делаю Junit. Я следовал примеру кода из примеров TomEE. Я сделал несколько изменений для лучшего понимания в классе обслуживания.

У меня есть 2 теста. 1. С транзакцией 2. Без транзакции

Первый тестовый пример работает хорошо. Но второй нет. Потому что второй метод запускает атрибут транзакции с никогда. Но все методы класса обслуживания имеют TA (Transaction Attribute) REQUIRED. Удалить транзакцию не зафиксировано, из-за этого мой контрольный пример не прошел.

Почему удаление транзакции не совершено? (хотя метод удаления требует ТП)

тогда как работает транзакция Add? (получение фильмов по методу GetMovies)

Entity @Сущность Кинотеатр общественного класса {

    @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 Ответ

0 голосов
/ 31 октября 2018

Вызов из нетранзакционного контекста: вы делаете удаление с отсоединенным экземпляром. Но вы создали сущность movie в другой транзакции. Поэтому сначала вам нужно выполнить слияние , чтобы сделать его управляемым объектом.

managedMovie = em.merge (movie);

em.remove (managedMovie);

См. Javadoc:

IllegalArgumentException - если экземпляр не является сущностью или является отдельной сущностью

...