容器托管事务无法回滚 [英] Container Managed Transactions can not rollback

查看:118
本文介绍了容器托管事务无法回滚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与交易打交道.

我将JPA配置为处理我的实体,并希望将其持久化在数据库中.问题是,当我的程序抛出runtimeException时,CMT将不会回滚.

I configured JPA to handle my Entitys, and want to persist them in the database. The problem is, CMT will not rollback, when my program throws an runtimeException.

这种容器的东西"背后的想法是如此难以理解,而且文献记载也很少.

The idea behind this "container thing" is so hard to understand and so poorly documented.

@transactional托管事务,纯CDI Interceptor托管事务和Bean托管事务都像魅力一样运作.

@transactional managed transactions, pure CDI Interceptor managed transactions and Bean Managed transactions are working like a charm.

这是我编写的代码:这是一个简单的电影演示".您想看两部X座电影.座位有限.如果电影席位不足,则不应进行交易(ACID和物品)

Here is what I coded: This is a simple "Cinema-Demonstration". you want to see two Movies with X seats. The Seats are limited. If there are not enough seats in Films, there should not be a Transaction (ACID and stuff)

在我的buyTicketsBoundary类中:

in my buyTicketsBoundary class:

首先,我告诉我的班级,我们正在使用CMT:

at first I tell my class we are using 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);
    }
}


正在通过JPA将已购买"票证写入数据库的Controller类:


The Controller class which is writing the Bought tickets in the Database via 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状态,而第二部电影引发异常时,数据库将无法回滚.

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.

我认为如果抛出RuntimeException,则容器会回滚

I thought if a RuntimeException was thrown, the Container would rollback

我该如何使它起作用?

What can I to to make it work?

请告诉我是否不清楚

推荐答案

我确实做了所有工作,唯一的错误是捕获了"myException"

I did everything corectly, the only error was to catch "myException"

} catch (MyException | IllegalStateException | SecurityException ex) {


} catch ( IllegalStateException | SecurityException ex) {

现在工作了,容器可以像应该的那样回滚

It woroks now and the container can rollback like it should

这篇关于容器托管事务无法回滚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆