Hibernate 在调用 Setter 时更新数据
Posted
技术标签:
【中文标题】Hibernate 在调用 Setter 时更新数据【英文标题】:Hibernate Updates Data When Calling 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 没有必要。我个人讨厌这种分离,并且总是在项目中与之抗争。 假设它毕竟是一种偏好......但我发现在构建响应时分离逻辑并避免此类问题更加清晰 是的,然后在将属性从一个对象复制到另一个对象时引入大量错误。 【参考方案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)
。我应该阅读什么来了解这些东西?以上是关于Hibernate 在调用 Setter 时更新数据的主要内容,如果未能解决你的问题,请参考以下文章
如果实体中没有getter和setter,为啥hibernate不会抛出异常
使用hibernate.get()取得对象再set()属性后调用update()更新对象时一直不能写入到数据库,是啥原因?