【问题标题】:Hibernate Updates Data When Calling SetterHibernate 在调用 Setter 时更新数据
【发布时间】:2018-02-17 11:45:16
【问题描述】:

我在数据库中有一个加密值,我想在发送到前端之前对其进行解密。 当我第一次将值保存为加密时,它在数据库中看起来像 -kKwj477382jle34nw。但是,如果我调用我的 getClientByUsername() 函数,我在这个函数中进行解密,当我在将对象发送到前端之前在对象中设置解密值时,数据库中的值也会自动更改。

@Transactional
public ResponseEntity <Client> getClientByUsername(String username) throws Exception {
  Client loggedClient = clientDAO.findByUsername(username);
  String data = loggedClient.getCreditCardNo();
  if (null != data) {
    @SuppressWarnings("static-access")
    byte[] encrypted = base64.decodeBase64(data);
    SecretKeySpec secretKeySpec = new SecretKeySpec(encryptionKey.getBytes(), algorithm);
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    decrypted = cipher.doFinal(encrypted);
    loggedClient.setCreditCardNo(new String(decrypted));
  }
  return new ResponseEntity < Client > (loggedClient, HttpStatus.OK);
}

这是我将值保存为加密的方式:

@Transactional
public boolean clientUpdate(String client) {
    str = updateclient.getCreditCardNo();
    if (null != str) {
      SecretKeySpec secretKeySpec = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), algorithm);
      Cipher cipher = Cipher.getInstance(algorithm);
      cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
      encrypted = cipher.doFinal(str.getBytes("UTF-8"));
      updateclient.setCreditCardNo(base64.encodeToString(encrypted));
      return clientDAO.updateProfileClient(updateclient);
    }

调用setter时如何阻止hibernate改变值?

更新

@PersistenceContext
private EntityManager entityManager;

public Client findByUsername(String username) throws Exception {
      Query query = entityManager.createNamedQuery("Client.findByUsername");
      query.setParameter("username", username);
      List result = query.getResultList();
      return result.size() > 0 ? (Client) result.get(0) : null;
    }

【问题讨论】:

  • 这是一个很好的例子,说明为什么您应该将实体与 dto 分开以进行响应。编辑:以及来自事务逻辑的控制器逻辑
  • @Zeromus 没有必要。我个人讨厌这种分离,并且总是在项目中与之抗争。
  • 假设它毕竟是一种偏好......但我发现在构建响应时分离逻辑并避免此类问题更加清晰
  • 是的,然后在将属性从一个对象复制到另一个对象时引入大量错误。

标签: java spring hibernate


【解决方案1】:

你需要在 Hibernate 的会话中 evict 这个对象:

void evict(Object object) throws HibernateException

从会话缓存中删除此实例。对实例的更改 不会与数据库同步。此操作级联到 如果关联被映射,则关联实例 cascade="evict"。

附:只是想,你也可以考虑另一种方法。您可以在 bean 中创建一个字段,将其标记为@Transient,即与数据库解耦,并将其命名为creditCardNoDecrypted。加密字段标记为@JsonIngore(或您用于序列化的任何内容)。

【讨论】:

  • 我相信使用 evict 是更好的方法,但我还没有弄清楚该怎么做
  • 这应该在clientDAO.findByUsername方法中完成
  • 我通过添加findByUsername 函数更新了我的答案。我正在使用EntityManager。我想我需要有hibernate.cfg.xml 才能使用SessionFactory,这是Session 需要的,但我没有。那么entityManager.refresh(obj) 是否与evict(Object obj) 做同样的事情,或者我应该怎么做?
  • 对于 JPA 使用 entityManager.detach(object)
  • 谢谢!它适用于entityManager.detach(object)。我应该阅读什么来了解这些东西?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-17
  • 2019-05-27
  • 1970-01-01
  • 2022-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多