Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何从EntityManager中分离实体

如何从EntityManager中分离实体
EN

Stack Overflow用户
提问于 2018-08-14 05:06:27
回答 3查看 2.3K关注 0票数 1

我的环境

Java 7/JPA 2/Hibernate 5.1。

我的情景

我正在构建一个存储库模式实现。所有的代码都是编写的,当没有发生错误情况时,所有代码都可以正常工作。

但是,假设将三个实体实例添加到存储库中。第一列和第三列都可以,但第二列缺少强制(非空)列的值。保存存储库时将返回DB错误。

当面对这种情况时,批处理过程应该只写一个日志消息,跳过无效的对象,然后继续到其他的对象。为了做到这一点,这个无效的实体只应该从存储库中删除,从存储库使用的底层EntityManager中分离它意味着什么。

我的问题

repository.exclude(entity)方法调用(在内部将实体与EntityManager分离)似乎不起作用,第二次保存存储库的尝试再次失败。

我的(部分) AbstractRepository类

代码语言:javascript
运行
AI代码解释
复制
public abstract class AbstractRepository<T> {
    private static Map<String,EntityManagerFactory> entityManagerFactories = new HashMap<String,EntityManagerFactory>();
    private static Map<EntityManagerFactory,EntityManager> entityManagers = new HashMap<EntityManagerFactory,EntityManager>();
    private EntityManager entityManager;
    private List<T> addedEntities = new ArrayList<T>();
    private List<T> deletedEntities = new ArrayList<T>();
    private List<T> updatedEntities = new ArrayList<T>();

    protected Class<T> entityClass = getEntityClass();

    // Many other declarations

    protected EntityManager createEntityManager() throws Exception {
        String persistenceUnitName = getPersistenceUnitName(); // using Reflection
        EntityManagerFactory entityManagerFactory = getEntityManagerFactory(persistenceUnitName);
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        return entityManager;
    }

    public T add(T entity) {
        addedEntities.add(entity);
        return entity;
    }

    public void save() throws Exception {
        EntityManager entityManager = getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction(); 
        transaction.begin();
        try {
            for(T entity : addedEntities)
                entityManager.persist(entity);
            for(T entity : updatedEntities)
                entityManager.merge(entity);
            for(T entity : deletedEntities)
                entityManager.remove(entity);
            transaction.commit();
        } catch(Exception e) {
            if(transaction.isActive())
                transaction.rollback();
            throw e;
        }
        addedEntities.clear();
        updatedEntities.clear();
        deletedEntities.clear();
    }

    public T exclude(T entity) throws Exception {
        if(entity == null)
            return null;
        addedEntities.remove(entity);
        deletedEntities.remove(entity);
        updatedEntities.remove(entity);
        getEntityManager().detach(entity);
        return entity;
    }

    public EntityManager getEntityManager() throws Exception {
        if(entityManager == null)
            entityManager = createEntityManager();
        return entityManager;
    }
}

我的仓库声明

代码语言:javascript
运行
AI代码解释
复制
@PersistenceUnit(unitName = "my-ds")
public class MestreRepository extends AbstractRepository<Mestre, Long> {
    public List<Mestre> all() throws Exception {
        List<Mestre> result = getEntityManager().createQuery("from Mestre", Mestre.class).getResultList();
        return result;
    }
}

我的测试代码

代码语言:javascript
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        MestreRepository allMestres = new MestreRepository();

        Mestre mestre1 = new Mestre();
        mestre1.setNome("Mestre 1");
        Mestre mestre2 = new Mestre(); // This one lacks Nome and will fail to be saved
        Mestre mestre3 = new Mestre();
        mestre3.setNome("Mestre 3");

        allMestres.add(mestre1);
        allMestres.add(mestre2);
        allMestres.add(mestre3);

        System.out.println("Saving 3 mestres");
        try {
            allMestres.save();
            System.out.println("All 3 mestres saved"); // never happens!
        } catch(Exception e) {
            System.out.println("Error when salving 3 mestres");
            try {
                System.out.println("Excluding mestre 2");
                allMestres.exclude(mestre2);
                System.out.println("Salving other 2 mestres");
                allMestres.save();
                System.out.println("All 2 mestres salved"); // never happens!
            } catch(Exception e2) {
                System.out.println("Still having errors");
            }
        }

        allMestres.close();
    }
}

我的persistence.xml

代码语言:javascript
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="my-ds" transaction-type="RESOURCE_LOCAL">
        <class>domain.Mestre</class>
        <class>domain.Detalhe</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <!-- Hibernate properties -->
            <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
            <property name="hibernate.connection.url" value="xxx"/>
            <property name="hibernate.connection.username" value="yyy"/>
            <property name="hibernate.connection.password" value="***"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
        </properties>
    </persistence-unit>
 </persistence>

更新了save()方法

下面是save()方法的一个新版本,它可以使事情正常工作。它需要在flush()之前调用commit(),对于那些没有造成任何问题的实体,不需要调用persist(),而是调用merge(),因为它们已经有了一个Id。

代码语言:javascript
运行
AI代码解释
复制
public void save() throws Exception {
    List<T> processedEntities = new ArrayList<T>();
    EntityManager entityManager = getEntityManager();
    EntityTransaction transaction = entityManager.getTransaction(); 
    transaction.begin();
    try {
        for(T entity : addedEntities) {
            entityManager.persist(entity);
            processedEntities.add(entity);
        }
        for(T entity : updatedEntities)
            entityManager.merge(entity);
        for(T entity : deletedEntities)
            entityManager.merge(entity);
        entityManager.flush();
        transaction.commit();
    } catch(Exception e) {
        updatedEntities.addAll(processedEntities);
        addedEntities.removeAll(processedEntities);

        if(transaction.isActive())
            transaction.rollback();
        throw e;
    }
    addedEntities.clear();
    updatedEntities.clear();
    deletedEntities.clear();
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-15 02:53:21

将评论转换为回答:

根据本指南,在分离实体之前需要flush()

更新OP的代码:

代码语言:javascript
运行
AI代码解释
复制
public void save() throws Exception {
    List<T> processedEntities = new ArrayList<T>();
    EntityManager entityManager = getEntityManager();
    EntityTransaction transaction = entityManager.getTransaction(); 
    transaction.begin();
    try {
        for(T entity : addedEntities) {
            entityManager.persist(entity);
            processedEntities.add(entity);
        }
        for(T entity : updatedEntities)
            entityManager.merge(entity);
        for(T entity : deletedEntities)
            entityManager.merge(entity);
        entityManager.flush();
        transaction.commit();
    } catch(Exception e) {
        updatedEntities.addAll(processedEntities);
        addedEntities.removeAll(processedEntities);

        if(transaction.isActive())
            transaction.rollback();
        throw e;
    }
    addedEntities.clear();
    updatedEntities.clear();
    deletedEntities.clear();
}
票数 4
EN

Stack Overflow用户

发布于 2022-04-11 11:12:51

  • 警诫

显然,单独使用merge进行更新是不够的。

代码语言:javascript
运行
AI代码解释
复制
for(T entity : updatedEntities)
        entityManager.merge(entity);

合并将将分离的实体状态(源)复制到托管实体实例(目标),因此,要从数据源更新实体,首先需要将它们带到托管状态,然后按您的意愿分离和静音detach实体,然后调用merge使其再次进入托管状态以与flushcommit同步。

因此,用于更新的适当代码如下所示

代码语言:javascript
运行
AI代码解释
复制
    public <T> BehindCacheDirector<R, V> update(Class<?> type, T t, Long v) {
            entityManager.detach(entityManager.find(type, v));
            entityManager.merge(t);
    ...        
    }

对于delete,您需要将要删除的实体更改为托管状态,然后将其状态更改为删除状态,然后调用同步命令,即

代码语言:javascript
运行
AI代码解释
复制
    public BehindCacheBuilder<R, V> remove(Class<?> type, Object object) {
        entityManager.remove(entityManager.find(type, object));
    ...
    }

这里中可以找到更多。

票数 0
EN

Stack Overflow用户

发布于 2018-08-14 05:12:18

不幸的是,在当前的JPA实现AFAIR中,无法将一个对象与实体管理器断开连接。

EntityManager.clear()将断开所有JPA对象的连接,因此在所有情况下,如果您计划保持连接的其他对象,这可能不是一个合适的解决方案。

所以,最好的选择是克隆对象,并将克隆传递给更改对象的代码。由于原始和不可变的对象字段是由默认的克隆机制以适当的方式处理的,所以您不必编写大量的管道代码(除了深入克隆任何聚合的结构之外)。

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51842232

复制
相关文章
jquery 元素尺寸
从上面的示例可以看到,使用width()和height()分别可以获取元素div的width和height的值。
Devops海洋的渔夫
2019/06/02
1.7K0
iPhone/iPad/Android UI尺寸规范
iPhone界面尺寸 设备 分辨率 PPI 状态栏高度 导航栏高度 标签栏高度 iPhone6 plus设计版 1242×2208 px 401PPI 60px 132px 146px iPhone6 plus放大版 1125×2001 px 401PPI 54px 132px 146px iPhone6 plus物理版 1080×1920 px 401PPI 54px 132px 146px iPhone6 750×1334 px 326PPI 40px 88px 98px iPhone5 - 5C -
红目香薰
2022/11/29
3.9K0
iPhone/iPad/Android UI尺寸规范
设备尺寸杂谈:响应性Web设计中的尺寸问题
目前在为移动设备设计界面时,最头疼的问题莫过于尺寸的问题。我们无法使用固定的尺寸来进行设计,因为不同设备的大小千变万化。但是如果我们了解了设备的物理特性后,这将有助于我们进行更好的设计。
大江小浪
2018/07/24
1.1K0
设备尺寸杂谈:响应性Web设计中的尺寸问题
获取元素尺寸宽高
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>获取元素尺寸宽高</title> 7 </head> 8 <style> 9 #div{ 10 background-color: #00ff00; 11 width: 60px; 12 height: 60px;
ProsperLee
2018/10/24
1.2K0
JavaScript DOM元素尺寸和位置
三大点: 1.获取元素CSS大小 2.获取元素实际大小 3.获取元素周边大小 一.获取元素CSS大小 1.通过style内联获取元素的大小 var box = document.getElementById('box');//获取元素 box.style.width;//200px、空 box.style.height;//200px、空 PS:style获取只能获取到行内style属性的CSS样式中的宽和高,如果有 获取;如果没有则返回空。 2.通过计算获取元素的大小 var style = windo
汤高
2018/01/11
2.8K0
响应式设计“让人们忘记设备的尺寸“
2012年 12月底,我国网民规模达到 5.64亿,互联网普及率为 42.1%,其中手机用户占网民总数的 74.5%。2014年,智能手机全球出货量达 12.86亿部,同比增长 28.0%。截至 2015年 1月,全球接入互联网的移动设备总数超过 70亿台,几乎平均全球人手一台。
博文视点Broadview
2020/06/11
5860
Android UI 开发里的尺寸单位理解
在学习 Android UI 开发的初期,经常被一些常用概念如 dp、sp 和它们与 px 的换算等虐,要避免被虐,最好的方法当然是知其所以然,再见到它们就胸中有料心不慌了。
mzlogin
2020/04/16
1.3K0
Android UI 开发里的尺寸单位理解
Android UI 开发里的尺寸单位理解
在学习 Android UI 开发的初期,经常被一些常用概念如 dp、sp 和它们与 px 的换算等虐,要避免被虐,最好的方法当然是知其所以然,再见到它们就胸中有料心不慌了。
零式的天空
2022/03/28
4140
jquery 与javascript 获取元素尺寸大小的对比
jquery获取尺寸的方法 width() 方法设置或返回元素的宽度(不包括内边距、边框或外边距)。 height() 方法设置或返回元素的高度(不包括内边距、边框或外边距)。
tianyawhl
2019/04/04
1.8K0
网页设计太麻烦
Bootstrap作为针对响应式设计和移动优先的前端web开发,是当下最流行的设计框架之一。使用 免费的Bootstrap UI工具包让原型设计和网页设计变得更加简单。
奔跑的小鹿
2019/06/15
3.9K0
响应式设计之子元素的数目检测
在响应式设计中,通用做法是根据屏幕尺寸,显示不用的样式。如果碰到需求,希望根据子节点的个数,显示不同的样式呢?
用户9127725
2022/08/08
5330
HenCoder UI 部分 2-2 全新定义 View 的尺寸
这期是 HenCoder 布局部分的第二期:重写 onMeasure() 来全新定制自定义 View 的尺寸。
扔物线
2018/08/20
2840
基于Combine的响应式UIControl
iOS开发中UIKit中控件的交互方式默认是Target-Action,这种方式简单且直观。不过,一个问题在于编码方式太过于繁琐,需要定义一个方法,然后调用addTartget方式进行绑定;在复杂页面交互,需要跨多级数据传递的时候,就变得异常繁琐。
用户8438817
2023/04/21
1K0
Android UI设计常用尺寸及基本知识
指实际的物理尺寸,为屏幕对角线的测量。 为了简单起见,Android把实际屏幕尺寸分为四个广义的大小:小,正常,大,特大。
全栈程序员站长
2022/07/02
2.7K0
Material Design —悬浮响应式按钮(Buttons: Floating Action Button)
自上次参加完回音分享会后,我下定决心要洗心革面乖乖打基础,于是开启了这个part,争取两个月不间断更新,写完Material Design与iOS中的组件(顺便学学英语),以便今后在使用的时候完全不虚
霖酱
2018/05/17
5.9K0
实践 | Google I/O 应用是如何适配大尺寸屏幕 UI 的?
5 月 18 日至 20 日,我们以完全线上的形式举办了 Google 每年一度的 I/O 开发者大会,其中包括 112 场会议、151 个 Codelab、79 场开发者聚会、29 场研讨会,以及众多令人兴奋的发布。尽管今年的大会没有发布新版的 Google I/O 应用,我们仍然更新了代码库来展示时下 Android 开发最新的一些特性和趋势。
Android 开发者
2022/03/10
2.1K0
实践 | Google I/O 应用是如何适配大尺寸屏幕 UI 的?
基于尺寸划分的RGB显著物体检测方法
SDCNet: Size Divide and Conquer Network for Salient Object Detection
计算机视觉
2021/01/12
4510
基于尺寸划分的RGB显著物体检测方法
强大的ConstraintLayout:使用ConstraintLayout打造响应式UI
约束布局ConstraintLayout发布(2017年)至今已经好几个年头了。经过几个版本的功能迭代,现阶段的ConstraintLayout相当强大,80%以上的复杂界面都可以使用ConstraintLayout来实现;剩下的20%里,有80%是没充分利用好ConstraintLayout的特性来实现,最后的20%,才是Android Support 包团队需要加油补上的。
Kkkiro
2019/07/19
3.1K0
15 个优秀的响应式 CSS 框架
响应式 Web 设计旨在为各种设备(从台式机显示器到手机)提供最佳的浏览体验。本文汇总了一些优秀的响应式 Web 设计 HTML 和 CSS 框架。这些框架都是开源的并免费的。
疯狂的技术宅
2021/02/25
11.5K0
15 个优秀的响应式 CSS 框架
点击加载更多

相似问题

改变startIcon / endIcon材料的尺寸-UI

39

基于JSON响应锚定UI元素

23

响应js材料-UI响应表

10

反应材料UI图标响应

17

用卡片响应材料UI响应网格

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档