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

复制
相关文章
WordPress 教程:WordPress 角色和权限终极指南
WordPress 在 2.0 版本中引入了角色和权限(Roles and Capabilities)系统,以前的用户等级的方法(User Levels)已经被弃用。但是还是有很多插件和主题仍然使用用户级别的方法来控制用户查看设置页面和其他功能。所以这篇指南将详细介绍 WordPress 的角色和权限系统,最终将让你在你的插件和主题中能够正确使用。
Denis
2023/04/15
2.2K0
用户、角色和权限
InterSystems IRIS®具有系统级安全性,以及一组与sql相关的额外安全性特性。 在数据库级保护之外,InterSystems SQL安全性提供了额外级别的安全功能。 SQL和系统级安全性之间的一些关键区别是:
用户7741497
2022/06/07
2.2K0
用户表的设计_角色和权限管理数据表设计
此时,在用户之上加一个userGroup用户组的概念。可给单个用户授权或特定用户组授权。
全栈程序员站长
2022/11/10
1.8K0
用户表的设计_角色和权限管理数据表设计
RBAC、控制权限设计、权限表设计 基于角色权限控制和基于资源权限控制的区别优劣
RBAC基于角色的访问控制(Role-Based Access Control)是按角色进行授权。例如:
宁在春
2022/10/31
2.9K0
RBAC、控制权限设计、权限表设计 基于角色权限控制和基于资源权限控制的区别优劣
PostgreSQL用户角色和权限管理
4、任何属于该组角色的对象都必须先被删除或者将对象的所有者赋予其它角色,任何赋予该组角色的权限也都必须被撤消。
数据和云
2022/02/25
4.9K0
PostgreSQL用户角色和权限管理
[NewLife.XCode]角色权限
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。
大石头
2019/07/02
2.2K0
【系统设计】基于角色的权限管理设计实现
内部运营系统的很多 API,涉及到外网正式环境下的用户信息变更。出于安全考虑,在设计之初保留了所有的操作记录,但这用于事后回查;真正要避免线上事故的发生,还需要权限管理。
心谭博客
2020/05/06
1.7K0
rbac权限管理设计 7表_数据库角色权限表设计
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。(如下图)
全栈程序员站长
2022/11/10
5.1K0
rbac权限管理设计 7表_数据库角色权限表设计
OushuDB-数据库角色和权限-权限
权限 当你创建一个数据库对象时,你就称为它的所有者。默认情况下,只有对象的所有者和超级管理员可以 对它进行任何操作。要允许其他角色使用它,必须要经过权限授予。 OushuDB中好多种不同的权限:SELECT, INSERT, DELETE, TRUNCATE, REFERENCES, TRIGGER, CREATE, CONNECT, TEMPORARY, EXECUTE 和 USAGE 。适用于特定对象的权限因对象类型不同而不 同。 修改或者删除一个对象的权限是对象所有者独有的权限。要改变一个表、索引、序列或者视图的所有 者,可以使用ALTER TABLE命令,对于其他的类型也有相应的ALTER命令。 要赋予权限,可以使用GRANT命令。如果fred是一个已经存在的用户,而department是一个已经存在 的表,可以用下面的命令更新表的权限: 在权限的位置写上ALL则赋予所有与该对象类型相关的权限。 授权给名为PUBLIC的特殊”用户”可以用于将权限赋予系统中的所有用户。 另外,还可以使用”组”角色来 帮助管理一群用户的权限。 最后,我们可以使用REVOKE命令撤销权限: ALTER ROLE name CREATEROLE CREATEDB; ALTER ROLE name WITH PASSWORD 'newpassword'; ALTER ROLE name WITH PASSWORD NULL;
用户7454708
2023/05/08
3590
asp.net MVC 权限设计
几点说明:     1、该权限系统是个网站用的,用户简单,因此不涉及到部门这些信息     2、基于将角色与controller、action相关联来判断用户是否有权     3、通过重载Aut
JadePeng
2018/03/12
3.4K1
asp.net MVC 权限设计
SAP Basis DEBUG改表数据权限角色设计
项目实践中,因种种原因不得不要通过debug才能解决一些特定的问题,所以就涉及到了debug权限角色的定义了。
SAP虾客
2021/01/23
8400
wordpress角色权限汇总
我们在用wordpress开发的时候有时候需要设置不同的用户组及权限,具体有哪些角色权限呢?随ytkah一起来看看吧。WordPress使用了角色的概念,旨在让站点所有者能够控制用户在站点中可以做什么和不能做什么。通过为每个用户分配特定的角色,站点所有者可以管理用户对诸如撰写和编辑文章、创建页面、创建类别、审核评论、管理插件、管理主题和管理其他用户等任务的访问。
ytkah
2019/11/04
9620
Oracle 角色及其权限
一、简介 Oracle权限分为系统权限和对象权限。 1、系统权限 注意:系统权限不支持级联回收,所以你需要使用sysdba一个个的回收。 2、对象权限 注:对象权限支持级联回收,系统权限不支持级联回收
郑小超.
2018/01/26
7680
oushudb-数据库角色和权限-数据库角色
数据库角色从概念上与操作系统用户是完全无关的,在实际使用中把它们对应起来可能比较方便。数据 库角色在整个数据库集群中是全局的,我么可以通过执行SQL 命令CREATE ROLE来创建一个角色,如 :
用户7454708
2023/05/08
3370
oracle--角色权限
将不同权限赋予角色,再将角色赋予用户,起到管理权限的作用 SQL> create role myrole; 角色已创建。 SQL> grant create session to myrole; 授权成功。 SQL> grant create table to myrole; 授权成功。 SQL> create user zs identified by zs; 用户已创建。 SQL> grant myrole to zs; 授权成功。 SQL> drop role myrole; 角色已删除。 SQL>
eadela
2019/09/29
7230
oracle--角色权限
WordPress 用户角色和其对应权限介绍
WordPress 中默认内置了五种注册用户角色(Role),分别是:管理员、编辑、作者、投稿者、订阅者。这四种用户类型分别拥有不同的权限和作用,共同构成了 WordPress 小巧却强大的用户系统。为什么说小巧又说强大?继续看下去你就会知道。
Denis
2023/04/14
1.5K0
WordPress 用户角色和其对应权限介绍
ASP.MVC 基于AuthorizeAttribute权限设计案例
     ASP.MVC上实现权限控制的方法很多,比如使用AuthorizeAttribute这个特性 1.创建自定义特性用于权限验证 public class AuthorizeDiy : AuthorizeAttribute { /// <summary> /// 提供一个入口用于自定义授权检查 /// </summary> /// <param name="httpContext"></param> /// <r
用户1055830
2018/01/18
1.6K0
ASP.MVC 基于AuthorizeAttribute权限设计案例
oushudb-数据库角色和权限
目录 操作角色的语句: create role db_role1; /--创建角色/ drop role db_role1; /--删除角色/ select rolename from pg_roles; /--查看所有角色/ /du --在命令格式下查看所有角色的命令 角色的权限 一个数据库角色可以有很多权限,这些权限定义了角色和拥有角色的用户可以做的事情。 create role db_role1 LOGIN; --创建具有登录权限的角色db_role1 create role db_role2 SUPERUSER; --创建具有超级用户权限的角色 create role db_role3 CREATEDB; --创建具有创建数据库权限的角色 create role db_role4 CREATEROLE --创建具有创建角色权限的角色 alter role db_role1 nologin nocreatedb; --修改角色取消登录和创建数据库权限 用户 其实用户和角色都是角色,只是用户是具有登录权限的角色。 create user db_user1 password '123'; --创建用户 create role db_user1 password '123' LOGIN; --同上一句等价 drop user db_user1; --删除用户 alter user db_user1 password '123456'; --修改密码 alter user db_user1 createdb createrole; --对用户授权 赋予角色控制权限 我们可以使用GRANT 和REVOKE命令赋予用户角色,来控制权限。 create user db_user1; --创建用户1 create user db_user2; --创建用户2 create role db_role1 createdb createrole; --创建角色1 grant db_role1 to db_user1,db_user2; --给用户1,2赋予角色1,两个用户就拥有了创建数据库和创 建角色的权限 revoke db_role1 from db_user1; --从用户1移除角色1,用户不在拥有角色1的权限 OushuDB 使用 角色 的概念管理数据库访问权限。 根据角色自身的设置不同,一个角色可以看做是一个 或者一组数据库用户。 角色可以拥有数据库对象(比如表)以及可以把这些对象上的权限赋予其它角色, 以控制谁拥有访问哪些对象的权限。另外,我们也可以把一个角色的 成员 权限赋予其它角色,这样就允 许成员角色使用分配给另一个角色的权限。
用户7454708
2023/05/08
2750
基于角色的菜单按钮权限的设计及实现
          思路:sql语句加上对应的where条件 ,来对查询到的所有数据做进一步的筛选。
明志德道
2023/10/20
7690
基于角色的菜单按钮权限的设计及实现
组织架构设计、角色与权限设计的一些思考
通常情况下有两种方式可以控制用户权限,一种是通过用户角色(Role)来控制权限,另一种是通过更细致的权限(Operation)来直接指定某个用户可以进行哪些行为。
房东的狗丶
2023/02/17
4550

相似问题

需要Enum设计指南

22

如何设计用户、角色和权限模式?

33

设计指南- CakePHP和MVC的新特性

12

我需要xml设计指南

122

mvc中的用户角色和权限

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

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

洞察 腾讯核心技术

剖析业界实践案例

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