2013-02-09 67 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