【问题标题】:JPA many to many Cascade issueJPA多对多级联问题
【发布时间】:2021-04-10 04:13:37
【问题描述】:

我有两个实体,我想在子项删除时将子项从父集中删除。 delete 函数会删除子实体,但不会从 ParentChild 表中删除记录。

所以我有以下问题:

2021-01-04 11:31:35.601 ERROR 14264 --- [  XNIO-1 task-2] c.f.timesheet.web.rest.AppUserResource   : Exception in getAppUser() with cause = 'javax.persistence.EntityNotFoundException: Unable to find com.freemind.timesheet.domain.Job with id 3351' and exception = 'Unable to find com.freemind.timesheet.domain.Job with id 3351; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.freemind.timesheet.domain.Job with id 3351'

我也有这个:

2021-01-04 11:31:35.598  WARN 14264 --- [  XNIO-1 task-2] o.h.e.loading.internal.LoadContexts      : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@55a124f7<rs=HikariProxyResultSet@372007568 wrapping org.postgresql.jdbc.PgResultSet@3901bf09>

实体:

工作(孩子):

@ManyToMany(mappedBy = "jobs", cascade = CascadeType.REFRESH,fetch = FetchType.LAZY)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonIgnore
private Set<AppUser> appUsers = new HashSet<>();

...

 public void removeAppUsers() {
        if (this.appUsers.size() > 0) 
            for (AppUser ap : this.appUsers) {
                log.debug("Request to delete Job from User : {}", ap);
                ap.removeJob(this);
                log.debug("Request to delete Job from User : {}", ap);
            }
    }

应用用户(父):

@ManyToMany(cascade = CascadeType.REFRESH,fetch = FetchType.LAZY)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JoinTable(
    name = "app_user_job",
    joinColumns = @JoinColumn(name = "internal_user_id"),
    inverseJoinColumns = @JoinColumn(name = "job_id", referencedColumnName = "id")
)
private Set<Job> jobs = new HashSet<>();

...

  public AppUser removeJob(Job job) {
        this.jobs.remove(job);
        job.getAppUsers().remove(this);
        return this;
    }

服务(@Service、@Transactionnal):

public void delete(Long id) {
    log.debug("Request to delete Job : {}", id);
    Job j=jobRepository.getOne(id);
    j.removeAppUsers();
    jobRepository.deleteById(id);
}

我做错了什么? 谢谢

【问题讨论】:

    标签: java spring-boot hibernate jpa jhipster


    【解决方案1】:

    我使用下面显示的代码对此进行了测试。问题似乎是您没有保存 AppUser 实例。

    AppUser 类

    package no.mycompany.myapp.misc;
    
    import lombok.Data;
    
    import javax.persistence.*;
    import java.util.HashSet;
    import java.util.Set;
    
    @Data
    @Entity
    public class AppUser {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @ManyToMany
        @JoinTable(
                name = "app_user_job",
                joinColumns = @JoinColumn(name = "internal_user_id"),
                inverseJoinColumns = @JoinColumn(name = "job_id", referencedColumnName = "id")
        )
        private Set<Job> jobs = new HashSet<>();
    
        Job addJob(Job job) {
            job.getAppUsers().add(this);
            this.jobs.add(job);
            return job;
        }
    
        void removeJob(Job job) {
            this.jobs.remove(job);
        }
    }
    

    AppUser 存储库

    package no.mycompany.myapp.misc;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface AppUserRepo extends JpaRepository<AppUser, Long> {}
    

    职位类别

    package no.mycompany.myapp.misc;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.*;
    import java.util.HashSet;
    import java.util.Set;
    
    @Getter
    @Setter
    @Entity
    public class Job {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @ManyToMany(mappedBy = "jobs")
        private Set<AppUser> appUsers = new HashSet<>();
    }
    

    工作报告

    package no.mycompany.myapp.misc;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface JobRepo extends JpaRepository<Job, Long> {}
    

    测试

    package no.mycompany.myapp.misc;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
    import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
    import org.springframework.test.context.ActiveProfiles;
    
    import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
    
    @DataJpaTest
    public class AppUserRepoTest {
    
        @Autowired
        TestEntityManager testEntityManager;
    
        @Autowired
        AppUserRepo appUserRepo;
    
        @Autowired
        JobRepo jobRepo;
    
        @Test
        public void test() {
    
            var appUser = testEntityManager.persist(createValidAppUser());
    
            var job1 = testEntityManager.persist(createValidJob());
            var job2 = testEntityManager.persist(createValidJob());
            var job3 = testEntityManager.persist(createValidJob());
    
            var appUserInDb = appUserRepo.getOne(appUser.getId());
    
            // add 3 jobs to AppUser instance
            var job1InDb = appUserInDb.addJob(jobRepo.getOne(job1.getId()));
            var job2InDb = appUserInDb.addJob(jobRepo.getOne(job2.getId()));
            appUserInDb.addJob(jobRepo.getOne(job3.getId()));
            appUserRepo.save(appUserInDb);
    
            // verify that AppUser instance has 3 jobs
            appUser = testEntityManager.find(AppUser.class, appUser.getId());
            assertThat(appUser.getJobs().size()).isEqualTo(3);
    
            // verify that job #1 instance has 1 AppUser instance
            job1 = testEntityManager.find(Job.class, job1.getId());
            assertThat(job1.getAppUsers().size()).isEqualTo(1);
    
            // remove 2 jobs from AppUser instance
            appUserInDb = appUserRepo.getOne(appUser.getId());
            appUserInDb.removeJob(job1InDb);
            jobRepo.delete(job1InDb);
    
            appUserInDb.removeJob(job2InDb);
            jobRepo.delete(job2InDb);
    
            appUserRepo.save(appUserInDb);
    
            // verify that AppUser instance has 1 job
            appUser = testEntityManager.find(AppUser.class, appUser.getId());
            assertThat(appUser.getJobs().size()).isEqualTo(1);
    
            // verify that job instances are deleted in db
            assertThat(testEntityManager.find(Job.class, job1.getId())).isNull();
            assertThat(testEntityManager.find(Job.class, job2.getId())).isNull();
        }
    
        private static AppUser createValidAppUser() {
            return new AppUser();
        }
    
        private static Job createValidJob() {
            return new Job();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-23
      • 2018-10-16
      • 2012-05-28
      • 1970-01-01
      • 2017-02-24
      • 2011-05-21
      • 1970-01-01
      相关资源
      最近更新 更多