栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在JPA中更改实体类型?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在JPA中更改实体类型?

所以我终于找到了一个可行的解决方案:

放弃 EntityManager 以更新 DTYPE 。这主要是因为 Query.executeUpdate()
必须在事务中运行。您可以尝试在现有事务中运行它,但这可能与您正在修改的实体的持久性上下文有关。这意味着更新 DTYPE之后, 您必须找到一种方法
evict() 实体。最简单的方法是调用 entityManager.clear(),
但这会导致各种副作用(请参阅JPA规范中的相关内容)。更好的解决方案是获取基础委托(在我的情况下为Hibernate Session )并调用
Session.evict(user) 。这可能适用于简单的域图,但是我的却非常复杂。我一直无法使
@Cascade(CascadeType.EVICT) 与我现有的JPA批注(如 @OneToOne(cascade =
CascadeType.ALL)
一起正常工作。我还尝试手动将域图传递给 会话,
并让每个父实体逐出其子代。由于未知原因,这也不起作用。

我被留在只有 entityManager.clear()
可以工作的情况下,但是我不能接受副作用。然后,我尝试创建专门用于实体转换的单独的持久性单元。我认为我可以将 clear()
操作本地化到仅负责转换的PC。我设置了一个新的PC,一个新的对应的 EntityManagerFactory ,一个新的Transaction
Manager,然后将该事务管理器手动注入到存储库中,以便在与正确的PC对应的事务中手动包装 executeUpdate()
。在这里我不得不说,我对Spring / JPA容器管理的交易还不甚了解,因为它最终成为试图获取本地/手动交易的噩梦。
executeUpdate() 可以很好地处理从Service层拉入的容器管理的事务。

在这一点上,我抛出了所有内容并创建了这个类:

@Transactional(propagation = Propagation.NOT_SUPPORTED)public class JdbcUserConversionRepository implements UserConversionRepository {@Resourceprivate UserService userService;private JdbcTemplate jdbcTemplate;@Override@SuppressWarnings("unchecked")public User convertUserType(final User user, final Class targetClass) {        // Update the DTYPE        jdbcTemplate.update("update user set user.DTYPE = ? where user.id = ?", new Object[] { targetClass.getSimpleName(), user.getId() });        // Before we try to load our converted User back into the Persistence        // Context, we need to remove them from the PC so the EntityManager        // doesn't try to load the cached one in the PC. Keep in mind that all        // of the child Entities of this User will remain in the PC. This would        // normally cause a problem when the PC is flushed, throwing a detached        // entity exception. In this specific case, we return a new User        // reference which replaces the old one. This means if we just evict the        // User, then remove all references to it, the PC will not be able to        // drill down into the children and try to persist them.        userService.evictUser(user);        // Reload the converted User into the Persistence Context        return userService.getUserById(user.getId());    }    public void setDataSource(final DataSource dataSource) {        this.jdbcTemplate = new JdbcTemplate(dataSource);    }}

我相信此方法可以使它起作用,它包含两个重要部分:

  1. 我已经用 @Transactional(propagation = Propagation.NOT_SUPPORTED) 对其进行了标记, 这应该挂起来自Service层的容器管理的事务,并允许在PC外部进行转换。
  2. 在尝试将转换后的实体重新加载到PC之前,我使用 userService.evictUser(user) 将当前存储在PC中的旧副本逐出 。为此的代码只是获取一个 Session 实例并调用 evict(user) 。有关更多详细信息,请参见代码中的注释,但是基本上,如果我们不这样做,则对 getUser的 任何调用都将尝试返回仍在PC中的缓存的Entity,除了会引发关于类型不同的错误。

尽管我的初始测试进展顺利,但此解决方案可能仍然存在一些问题。由于它们被发现,我将保持更新。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/468900.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号