2013-02-09 63 views
1

嗨我想記錄異常到DB記錄異常到DB - Java的春天

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") 
} 

我有一個LoggerImpl類記錄異常的詳細信息到數據庫。 只有UserDefinedException得到記錄,因爲空指針異常不是。任何一個Plz能幫助我嗎?

LogEntry.java

private long id; 
private String desc; 

// getters and setters 

Logger.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被使用序列增量器

生成我使用陳JTA saction經理。

+0

能否請您發表調用insertLog(..)方法的代碼? – dimas 2013-02-09 10:09:58

+0

我已編輯的代碼包括調用insertLog() – crazyProgrammer 2013-02-09 11:18:56

回答

1

你,因爲你的情況LoggerImplementation類不是由Spring容器和容器管理(因爲它應該是)對insertLog(..)方法不會啓動新的交易得到了這樣的結果。爲了讓這個類管理你應該注入你的bean。我建議你做這樣的重構。這將工作。

而不必記錄器和LoggerImpl類創建記錄器接口和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"); 
    } 
} 

現在將外部事務回滾,但內部新事務將數據寫入數據庫。

的rollbackFor@Transactional註解爲TestService的類屬性。這是必要的,因爲默認情況下Spring不會回滾事務以查找異常。這是你所描述的行爲。在你的情況下,只有運行時異常纔會回滾外部事務。這就是爲什麼當您嘗試記錄NullPointerException時,整個事務回滾並且日誌記錄未添加到數據庫。但是,當您嘗試記錄UserDefinedException事務成功提交時,儘管已拋出錯誤並且您的日誌記錄已寫入數據庫。

+0

的方法,但爲什麼是UserDefinedException中得到記錄和NullPointerException異常是不是? – crazyProgrammer 2013-02-09 13:27:51

+0

因爲UserdefinedException是檢查異常(據我所知)。默認情況下,Spring在檢查異常時不會回滾事務。如果你想改變這種行爲,將rollbackFor屬性設置爲Exception.class。我在最後一句中寫了這個。 – dimas 2013-02-09 13:31:56

+0

如果在您的第​​一個示例中,您將從RuntimeException類擴展UserDefinedException,那麼它將不會被記錄。 – dimas 2013-02-09 13:33:30