1

こんにちは、DB に例外を記録しようとしています

public void a(){
        try{

              String c = b();
           }catch (Throwable ex){
                   com.log.Logger.log(ex);
                   throw new UserDefinedException(ex);
           }
        }

public String b(){
               throw new NullPointerException("Transaction Logger")
}

例外の詳細を DB に記録する LoggerImpl クラスがあります。UserDefinedException のみがログに記録されますが、Null ポインター例外は記録されません。誰でも助けてくれませんか。

LogEntry.java

private long id;
private String desc;

// getters and setters

ロガー.java

public long log(Throwble ex){

    LogEntry entry = new LogEntry();
    entry.setDesc(ex.getMessage());
    LoggerImpl log = new LoggerImpl();
    log.insertLog(entry);
    return entry.getId();
}

LoggerImpl.java

@Transactional(propogation = PROPOGATION.REQUIRES_NEW)
public void insertLog(LogEntry log){
    insert.update(//fields);
}

Id は Sequence Incrementer を使用して生成されます

JTA トランザクション マネージャーを使用しています。

4

1 に答える 1

2

このような結果が得られたのは、あなたのケースでは LoggerImplementation クラスが Spring コンテナーによって管理されておらず、コンテナーが insertLog(..) メソッドの新しいトランザクションを開始しないためです (想定どおり)。このクラスを管理対象にするには、Bean に注入する必要があります。そのようなリファクタリングを行うことを提案します。これは機能します。

Logger および LoggerImpl クラスで Logger インターフェイスと、このインターフェイスを実装する LoggerImpl クラスを作成する代わりに。

public interface Logger {

    long log(Throwable ex);

}

@Transactional
@Component
public final class LoggerImpl implements Logger {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public long log(Throwable ex) {
        LogEntry entry = new LogEntry();
        entry.setDescription(ex.getMessage());

        entityManager.persist(entry);

        return entry.getId();
    }

}

次に、例外ロガーを必要なサービスクラスに挿入するだけです。例えば:

@Transactional(rollbackFor=Exception.class)
@Service
public class TestService {

    @Autowired
    private Logger logger;

    public void a() throws UserDefinedException {
        try {

            b();
        } catch (Throwable ex) {
            logger.log(ex);
            throw new UserDefinedException(ex);
        }
    }

    public String b() {
        throw new NullPointerException("Transaction Logger");
    }
}

外側のトランザクションはロールバックされますが、内側の新しいトランザクションはデータを DB に書き込みます。

TestService クラスの@TransactionalアノテーションのrollbackFor属性に注意してください。デフォルトでは、Spring は、chacked 例外のトランザクションをロールバックしないため、これが必要です。これは、あなたが得た動作を説明しています。あなたの場合、外側のトランザクションは実行時例外に対してのみロールバックされました。そのため、NullPointerException をログに記録しようとすると、トランザクション全体がロールバックされ、ログ レコードが DB に追加されません。しかし、UserDefinedException をログに記録しようとすると、エラーがスローされ、ログ レコードが DB に書き込まれているにもかかわらず、トランザクションが正常にコミットされます。

于 2013-02-09T12:32:33.103 に答える