简体   繁体   English

通过JPA更新对象并获取旧值

[英]Update object and get old value via JPA

I want to log changes of an account. 我想记录帐户的更改。 Therefore, I have created an entity class that shall log the changes. 因此,我创建了一个实体类,用于记录更改。 Each time, an account entity is saved or updated a logging object is created. 每次保存或更新帐户实体时都会创建日志记录对象。

When the object is updated with a new balance the old balance shall be retrieved from the database. 使用新余额更新对象时,应从数据库中检索旧余额。 As the object is bound to the session retrieving its old balance is not trivial, because one always gets the new balance. 由于对象绑定到会话检索其旧余额并不简单,因为总是得到新的余额。

To circumvent, I detached the object from the session. 为了规避,我将对象从会话中分离出来。 Yet, this seems to be a workaround that should be avoided. 然而,这似乎是一个应该避免的解决方法。

The following code snippets shall illustrate the scenario. 以下代码片段将说明该方案。

Any suggestion is highly appreciated! 任何建议都非常感谢!

The test: 考试:

public class AccountServiceTest
{
    @Autowired
    AccountService        accountService;

    @Autowired
    ChangeAccountService  changeAccountService;

    @Test
    public void shouldHaveChangeLog()
    {
        Account account = this.accountService.updateAccount(new Account(0, 10.0));
        assertThat(account.getId(), is(not(0L)));

        account.setBalance(20.0);
        account = this.accountService.updateAccount(account);

        final List<ChangeAccountLog> changeResultLogs = this.changeAccountService.findAll();
        assertThat(changeResultLogs.get(1).getNewBalance(), is(not(changeResultLogs.get(1).getOldBalance())));
    }
}

The service of the domain class to be logged: 要记录的域类的服务:

@Service
public class AccountService
{
    @Autowired
    AccountRepository accountRepository;

    @Autowired
    ChangeAccountService  changeAccountService;

    public Account findById(final long id)
    {
        return this.accountRepository.findOne(id);
    }

    public Account updateAccount(final Account account)
    {
        this.changeAccountService.saveLog(account);

        return this.accountRepository.save(account);
    }
}

The service of the logging class: 日志记录类的服务:

@Service
public class ChangeAccountService
{
    @Autowired
    AccountService                accountService;

    @Autowired
    ChangeAccountLogRepository    repository;

    public ChangeAccountLog save(final ChangeAccountLog changeAccountLog)
    {
        return this.repository.save(changeAccountLog);
    }

    public List<ChangeAccountLog> findAll()
    {
        return this.repository.findAll();
    }

    public ChangeAccountLog saveLog(final Account account)
    {
        final Double oldAccountBalance = oldAccountBalance(account);
        final Double newAccountBalance = account.getBalance();
        final ChangeAccountLog changeAccountLog = new ChangeAccountLog(0, oldAccountBalance, newAccountBalance);

        return this.repository.save(changeAccountLog);
    }

    @PersistenceContext
    EntityManager   em;

    private Double oldAccountBalance(final Account account)
    {
        this.em.detach(account);

        final Account existingAccount = this.accountService.findById(account.getId());

        if (existingAccount != null)
        {
            return existingAccount.getBalance();
        }
        return null;

    }
}

The class of which objects are to be logged: 要记录哪些对象的类:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Account
{
     @Id
     @GeneratedBalance
     protected    long    id;

     Double balance;
}

The logging class: 记录类:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class ChangeAccountLog
{
     @Id
     @GeneratedBalance
     private long     id;

     private Double    oldBalance;
     private Double    newBalance;
}

您可能希望使用Hibernate Envers来创建版本控制表,而不是创建单独的日志对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM