简体   繁体   English

容器托管事务无法回滚

[英]Container Managed Transactions can not rollback

I am playing arround with transactions. 我正在与交易打交道。

I configured JPA to handle my Entitys, and want to persist them in the database. 我将JPA配置为处理我的实体,并希望将它们持久保存在数据库中。 The problem is, CMT will not rollback, when my program throws an runtimeException. 问题是,当我的程序抛出runtimeException时,CMT将不会回滚。

The idea behind this "container thing" is so hard to understand and so poorly documented. 这种“容器的东西”背后的想法是如此难以理解,而且文献记载也很少。

@transactional managed transactions, pure CDI Interceptor managed transactions and Bean Managed transactions are working like a charm. @transactional托管事务,纯CDI Interceptor托管事务和Bean托管事务的运行就像是一种魅力。

Here is what I coded: This is a simple "Cinema-Demonstration". 这是我编写的代码:这是一个简单的“电影演示”。 you want to see two Movies with X seats. 您想看两部X座电影。 The Seats are limited. 座位有限。 If there are not enough seats in Films, there should not be a Transaction (ACID and stuff) 如果电影席位不足,则不应进行交易(ACID和物品)


in my buyTicketsBoundary class: 在我的buyTicketsBoundary类中:

at first I tell my class we are using CMT: 首先,我告诉班级我们正在使用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);
    }
}

My Exception: 我的例外:

@ApplicationException(rollback=true)
public class MyException extends RuntimeException{
    public MyException()  {

    }

    public MyException(String s) {
        System.out.println(""+s);
    }
}

The Controller class which is writing the Bought tickets in the Database via JPA: 通过JPA将“已购买”票证写入数据库的Controller类:

@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();
}
}

the problem is, when this class reaches the em.persist state for the first movie, and the second movie throws an exception, the database can not rollback. 问题是,当此类达到第一部电影的em.persist状态,而第二部电影引发异常时,数据库无法回滚。

I thought if a RuntimeException was thrown, the Container would rollback 我以为如果抛出RuntimeException,容器将回滚

What can I to to make it work? 我该怎么做才能使其正常工作?

Plase tell me if something is not clear 请告诉我是否不清楚

I did everything corectly, the only error was to catch "myException" 我确实做了所有事情,唯一的错误是捕获了“ myException”

} catch (MyException | IllegalStateException | SecurityException ex) {

} catch ( IllegalStateException | SecurityException ex) {

It woroks now and the container can rollback like it should 现在它很糟糕,容器可以像应该的那样回滚

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM