Контейнер Управляемые транзакции не может откат
Я играю с транзакциями.
Я настроил JPA для обработки своих сущностей и хочу сохранить их в базе данных. Проблема в том, что CMT не будет выполнять откат, когда моя программа генерирует исключение runtimeException.
Идея, лежащая в основе этой "контейнерной вещи", так сложна для понимания и так плохо документирована.
управляемые транзакции @transactional, чисто управляемые транзакции CDI Interceptor и управляемые bean-транзакции работают как шарм.
Вот что я кодировал: Это простая "Демонстрация кино". Вы хотите увидеть два фильма с X местами. Количество мест ограничено. Если в фильмах недостаточно мест, не должно быть транзакции (ACID и прочее)
в моем классе buyTicketsBoundary:
сначала я говорю своему классу, что мы используем CMT:
@Named("buchungBoundry")
@RequestScoped
@TransactionManagement(TransactionManagementType.CONTAINER)
public class BuchungBoundry {
@EJB
private BuchungVerwaltung buyTicketsController;
@EJB
private KundenVerwaltung customerController;
@EJB
private SaalVerwaltung roomController;
@EJB
private MovieVerwaltung movieController;
private int ticketsForMovie1; //this is how many tickets we want to buy
private int ticketsForMovie2;
public BuchungBoundry() {
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void buyTickets() throws MyException {
int numberOfSeantsInRoom1=roomController.getSaal(4).getAnzahlPlaetze();
int numberOfSeantsInRoom2=roomController.getSaal(5).getAnzahlPlaetze();
int alreadyBoughtSeatsIn1=buyTicketsController.getBelegtePlatzeNachSaal(4);
int alreadyBoughtSeatsIn2=buyTicketsController.getBelegtePlatzeNachSaal(5);
int availableSeats1 = numberOfSeantsInRoom1 - alreadyBoughtSeatsIn1;
int availableSeats2 = numberOfSeantsInRoom2 - alreadyBoughtSeatsIn2;
System.out.println("Saal A: ("+alreadyBoughtSeatsIn1+"/"+numberOfSeantsInRoom1+") want to buy :" + ticketsForMovie1);
System.out.println("Saal B: ("+alreadyBoughtSeatsIn2+"/"+numberOfSeantsInRoom2+") want to buy :" + ticketsForMovie2);
try {
if (ticketsForMovie1 <= availableSeats1) {
buyTicketsController.erstelleBuchung(customerController.getKunde(1),
movieController.getMovie(7),
roomController.getSaal(4),
ticketsForMovie1);
} else {
throw new MyException("ERROR: no room for "
+ ticketsForMovie1 + " person! "
+alreadyBoughtSeatsIn1);
}
if (ticketsForMovie2 <= availableSeats2) {
buyTicketsController.erstelleBuchung(customerController.getKunde(1),
movieController.getMovie(8),
roomController.getSaal(5),
ticketsForMovie2);
} else {
throw new MyException("ERROR: no room for "
+ ticketsForMovie2 + " person! "
+alreadyBoughtSeatsIn2);
}
} catch (MyException | IllegalStateException | SecurityException ex) {
Logger.getLogger(BuchungBoundry.class.getName()).log(Level.SEVERE, null, ex);
}
}
Мое исключение:
@ApplicationException(rollback=true)
public class MyException extends RuntimeException{
public MyException() {
}
public MyException(String s) {
System.out.println(""+s);
}
}
Класс Controller, который записывает купленные билеты в Базу данных через JPA:
@Stateless
public class BuchungVerwaltung implements Serializable {
@PersistenceContext(unitName = "kbse-JTA")
private EntityManager em;
public BuchungVerwaltung() {
}
public void erstelleBuchung(Kunde k, Movie movie, Saal saal, int anzahlPlaetze) {
Buchung b = new Buchung(k, movie, saal, anzahlPlaetze);
em.persist(b);
}
public int getBelegtePlatzeNachSaal(int id) {
try {
Query query = em.createNativeQuery("select sum(b.ANZAHL) from SAAL s,BUCHUNG b where s.SAAL_ID = b.SAAL_SAAL_ID and s.SAAL_ID=?");
query.setParameter(1, id);
return (int) query.getSingleResult();
} catch (Exception e) {
return 0;
}
}
public List<Buchung> getAlleBuchungen() {
TypedQuery<Buchung> query = em.createQuery("select s from Buchung s", Buchung.class);
return query.getResultList();
}
}
проблема в том, что когда этот класс достигает состояния em.persist для первого фильма, а второй фильм вызывает исключение, база данных не может выполнить откат.
Я думал, что если выдается RuntimeException, контейнер будет откат
Что я могу сделать, чтобы это работало?
Скажите, пожалуйста, если что-то не понятно
1 ответ
Я сделал все по-своему, единственной ошибкой было перехватить "myException"
} catch (MyException | IllegalStateException | SecurityException ex) {
} catch ( IllegalStateException | SecurityException ex) {
Теперь он работает, и контейнер может откатиться так, как должен