代码之家  ›  专栏  ›  技术社区  ›  Jovan0042

在H2中持久化多个实体引发异常

  •  1
  • Jovan0042  · 技术社区  · 6 年前

    我有两个实体,其中两个都有彼此的列表。

    类别“Post”:

    @ManyToMany(mappedBy = "posts", cascade=CascadeType.ALL)
    private List<Tag> tags;
    

    类别“Tag”:

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable
    private List<Post> posts;`
    

    在db中,我有许多关系的“POSTS”表、“TAGS”表和“TAGS\u POSTS”。数据库中的结构和数据库中的表都很好。但当我开始在Posts表中持久化Post entiti时,出现了错误。

    这是用于向db添加新帖子的代码,同样的代码适用于其他实体,即使是“标记”,也有很多关系。

    private EntityManagerFactory emf;
    
    @PersistenceUnit
    public void setEmf(EntityManagerFactory emf) {
        this.emf = emf;
    }
    
    public Post add(Post post) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.persist(post);
        em.getTransaction().commit();
        return post;
    }
    

    现在,在应用程序开始时,我尝试用一些虚拟数据填充db进行测试。除Post外,其他所有具有相同代码的实体都运行良好。

    下面是代码(我在没有设置tags属性的情况下尝试过,将其设置为空ArrayList,将其设置为db result中已经存在的标记的列表是一样的):

     ApplicationContext ac =  SpringApplication.run(PostsPortalApplication.class, args);
    
    
     PostsService ps = (PostsService) ac.getBean("postsService");
    
     Post post = new Post();
     post.setId(j);
     post.setDate(new Date());
     post.setDescription("desc" +  "/" );
     post.setDislikes(5);
     post.setLikes(5);
     post.setLocationLat(5);
     post.setLocationLong(5);
     post.setPhotoUrl("URL" +  "/" + j);
     post.setTitle("Title"  + "/" + j);
     post.setUser(user);
     post.setTags(new ArrayList<>());
     ps.add(post);
    

    这是异常消息(postservice.java:38是第行): em.persist(post);

    线程“main”javax中出现异常。坚持不懈PersistenceException:组织。冬眠PersistentObjectException:传递给persist:jovan的分离实体。sf\U 62\U 2017。运动后。波乔。邮递 位于组织。冬眠内部的例外ConverterImpl。转换(ExceptionConverterImpl.java:149) 位于组织。冬眠内部的例外ConverterImpl。转换(ExceptionConverterImpl.java:157) 位于组织。冬眠内部的例外ConverterImpl。转换(ExceptionConverterImpl.java:164) 位于组织。冬眠内部的SessionImpl。firePersist(SessionImpl.java:789) 位于组织。冬眠内部的SessionImpl。持久化(SessionImpl.java:767) 在太阳下。反映NativeMethodAccessorImpl。invoke0(本机方法) 在太阳下。反映NativeMethodAccessorImpl。调用(NativeMethodAccessorImpl.java:62) 在太阳下。反映DelegatingMethodAccessorImpl。调用(DelegatingMethodAccessorImpl.java:43) 在java。lang.reflect。方法调用(Method.java:498) 位于组织。springframework。orm。jpa。ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler。调用(ExtendedEntityManagerCreator.java:350) 在com。太阳代理$Proxy85。持久化(未知源) 在jovan。sf\U 62\U 2017。运动后。服务。实施。售后服务。add(PostsService.java:38) 在jovan。sf\U 62\U 2017。运动后。运动后应用程序。main(PostsPortalApplication.java:67)

    原因:组织。冬眠PersistentObjectException:传递给persist:jovan的分离实体。sf\U 62\U 2017。运动后。波乔。邮递 位于组织。冬眠事件内部的DefaultPersistEventListener。onPersist(DefaultPersistEventListener.java:124) 位于组织。冬眠事件内部的DefaultPersistEventListener。onPersist(DefaultPersistEventListener.java:58) 位于组织。冬眠内部的SessionImpl。firePersist(SessionImpl.java:782) 。。。9个以上

    2 回复  |  直到 6 年前
        1
  •  1
  •   Solmaz Oskouie    6 年前

    首先,请更改:

    cascade=CascadeType.ALL
    

    收件人:

    cascade = {CascadeType.PERSIST, CascadeType.MERGE}
    

    因为级联类型。使用CascadeType时会自动继承REMOVE。所有,但实体删除不仅应用于链接表,还应用于关联的另一端。( see hear )

    请尝试以下代码:

        @ManyToMany(mappedBy = "posts", 
                cascade = {CascadeType.PERSIST, CascadeType.MERGE})
        private List<Tag> tags;
    
    
    
    
    @ManyToMany(cascade = 
            {CascadeType.PERSIST, CascadeType.MERGE})
        @JoinTable(name = "post_tag",
            joinColumns = {
                @JoinColumn(
                    name = "tag_id", 
                    referencedColumnName = "id"
                )
            },
            inverseJoinColumns = {
                @JoinColumn(
                    name = "post_id", 
                    referencedColumnName = "id"
                )
            }
        )
    private List<Post> posts;
    

    但你的问题。。。。 尝试使用persist方法将分离的对象(表示该对象的实例已保存到DB中,但该对象不在会话中)保存到DB:

     Post post = new Post();
     post.setId(j);
     .
     .
     .
     em.persist(post)
    

    persist方法用于添加 新建实体 (不设置id)实例到持久性上下文,即将实例从瞬态转换为持久性状态。

    我们通常在需要向数据库插入记录时调用它(持久化实体实例) 所以 如果对象具有瞬态或持久状态,则可以使用persist方法,但如果在分离对象之前,应使用merge方法保存它

        2
  •  0
  •   sam    6 年前

    而不是这样:

    @许多(级联=级联型。所有) @可合并私有列表(<发布(>);岗位;

    请尝试以下操作:

    private List<Post> posts = new ArrayList<>();
    
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
        name = "posts_tags",
                joinColumns = { @JoinColumn(name = "fk_tags") },
                inverseJoinColumns = { @JoinColumn(name = "fk_posts") }
    )
    public List<Post> getPosts() {
        return posts;
    }
    
    public void setPosts(List<Post> posts) {
        this.posts = posts;
    }
    

    在这里,hibernate将为多对多关系映射创建一个名为(posts\u tags)的中间表。

    现在让我们简化DAO服务:

    @PersistenceContext(unitName = "myPersistenceUnit")
    private EntityManager em;
    
    @Transactional(value = "myTransactionManager",propagation = Propagation.REQUIRED)
    public Post add(Post post) {
        em.persist(post);
        return post;
    }