2

私はトランザクションで遊んでいます。

エンティティを処理するように JPA を構成し、それらをデータベースに保持したいと考えています。問題は、プログラムが runtimeException をスローしたときに、CMT がロールバックしないことです。

この「コンテナのこと」の背後にある考え方は、理解するのが非常に難しく、文書化も不十分です。

@transactional マネージド トランザクション、純粋な CDI Interceptor マネージド トランザクション、および Bean マネージド トランザクションは魅力的に機能します。

これが私がコーディングしたものです。これは単純な「シネマデモ」です。X 席の映画を 2 つ見たいとします。席数に限りがございます。フィルムに十分な座席がない場合、トランザクション (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);
    }
}

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

問題は、このクラスが最初のムービーの em.persist 状態に達し、2 番目のムービーが例外をスローすると、データベースがロールバックできないことです。

RuntimeException がスローされた場合、コンテナはロールバックすると思いました

それを機能させるにはどうすればよいですか?

不明な点があれば教えてください

4

1 に答える 1

0

私はすべてを正確に行いました。唯一のエラーは「myException」をキャッチすることでした

} catch (MyException | IllegalStateException | SecurityException ex) {

} catch ( IllegalStateException | SecurityException ex) {

現在は機能しており、コンテナは本来のようにロールバックできます

于 2014-05-25T00:34:18.303 に答える