【问题标题】:How to save logs to database in AOP advice如何在 AOP 建议中将日志保存到数据库
【发布时间】:2019-06-24 14:25:33
【问题描述】:

我在使用 Spring AOP 时在数据库中保存日志(或任何其他信息)时遇到问题。

这是问题的根源:

@Aspect
@Configuration
@Component
@EnableAspectJAutoProxy
public class LoggingAspect {

    @Autowired
    private LogService logService;

    @AfterThrowing(pointcut = "execution(* org.springframework.web.client.RestTemplate+.*(..))", throwing = "ex")
    public void logError(Exception ex) {
        Log log = new Log("Error!");
        logService.save(log);
    }
}

logService 实例是一个简单的@Service 类,它在内部调用@Repository 方法。没什么特别的。 Log 类更简单:)它只包含一个变量(如果我们包含 id,则为两个):

@Entity
@Table
public class Log {
    @Id
    private Long id;

    @Column
    private String message;

    //getters, setters, constructors, etc.
}

LoggingAspect 工作正常。 @AfterThrowing 建议在任何异常的情况下被正确调用。但是在调用save 方法后,数据库中没有保存任何内容。 当我尝试调用 getAll() 方法而不是 save 时,一切都按预期工作。所有数据都从数据库中加载。 此问题仅适用于save 方法。

如有任何提示,我将不胜感激。

编辑:
正如我之前提到的,@Service@Repository 类目前非常基础。也许值得补充的是,外部方面类一切都运行良好。可以将日志保存在数据库中。此问题仅在保存时出现,并且仅在用于各种建议时才会出现。 添加服务代码

@Service
public class LogService {

    @Autowired
    private LogRepository logRepository;

    @Transactional(readOnly = true)
    public List<Log> getAllLogs() {
        return logRepository.findAll();
    }

    @Transactional
    public void save(Log log) {
        logRepository.save(log);
    }
}

添加了代码库

@Repository
public interface LogRepository extends JpaRepository<Product, Log> {
}

【问题讨论】:

  • 请张贴LogService代码
  • @ThomasAndolf LogService 代码添加
  • 你有@EnableJpaRepositories 吗?
  • 不,但我使用 Spring Boot,所以我认为它是通过自动配置自动启用的。正如我在“编辑”中提到的那样 - 在方面类之外一切正常
  • 供参考By default, CRUD methods on repository instances are transactional. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain @Transactional so that default transaction configuration applies. docs.spring.io/spring-data/jpa/docs/2.1.8.RELEASE/reference/…

标签: spring spring-boot aop spring-aop


【解决方案1】:

听起来像事务处理。

但更多信息会更好,我只能在这里猜测。如果您还没有检查,那么需要检查的几点。

我猜你把@Transational 放在服务或存储库上,对吧?还要确保您在 Spring 默认代理机制中具有单独的类中的 Repository、Service。

为 jpa、hibernate 和 spring 事务调试和添加日志记录。

【讨论】:

  • @Trasactional 用于我的 Service 类,当然 Repository 和 Service 在单独的类中。我想这是某种交易问题,但我还不知道如何解决。当我调试我的代码时,一切似乎都很好。例如 logRepository.save(log); 方法返回保存的实体(设置了 id 值)但数据库中没有更改。我还看到休眠将一些插入记录到数据库中,但仍然......数据库中没有任何变化。我将尝试为 jpa、hibernate、spring 启用所有日志。我知道这很容易修复,但我已经花了三天时间,我已经受够了
  • Service and Repository 看起来不错,所以一定是一些missconfig 或Aspüect 处理。无法帮助您,抱歉。
  • 如果没有任何帮助,您可以手动进行交易:UserTransaction utx = entityManager.getTransaction();试试 {utx.begin();商业逻辑(); utx.commit(); } 捕捉(异常前) { utx.rollback();扔前; }
  • 为什么你的 Aspejt 配置中有 @Component?
  • 章节:dzone.com/articles/how-does-spring-transactional 上的“事务方面”。这让我回到了“承诺”缺失理论。
【解决方案2】:

好的。我找到了解决办法! 我怀疑这是一个交易问题。无论任何现有事务如何,都必须启动新事务。所以@Service 类中缺少一行(或者更确切地说是事务属性)

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Log log) {
    logRepository.save(log);
}

感谢所有帮助解决问题的人。

【讨论】:

  • 我忍不住要说一句:“我怀疑”?你没有怀疑任何事情,甚至没有提到交易。用户@R.S 在他的回答中提到了这一点。所以请做个绅士,给这个家伙一些功劳,而不是假装自己解决了这一切。
  • 我提到我怀疑交易存在问题,但我不知道究竟是什么问题 - “我想这是某种交易问题,但我还不知道如何解决它。 ”。但我同意 R.S 的回答很有帮助,所以我投票支持他的帖子
  • 这是您在 R.S 回答下的评论,所以他建议这样做。你后来才确认。在别人首先提到它之后,为自己提出这个想法总是很容易的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
相关资源
最近更新 更多