当前位置: 首页 > 知识库问答 >
问题:

支持读取和删除但不支持插入的一对多关系

公冶峰
2023-03-14

我想将前面文章中提到的要求扩展到支持删除。我们有两个数据模型对象组织和部门共享一对多的关系。通过下面的映射,我可以从organization对象读取部门列表。我没有添加cascade ALL属性来限制在创建组织时添加部门。

@Entity
@Table(name="ORGANIZATIONS")
public class Organization{

    @Id
    @GeneratedValue
    Private long id;

    @Column(unique=true)
    Private String name;

    @OneToMany(mappedBy = "organization", fetch = FetchType.EAGER)
    private List<Department> departments;


}

@Entity
@Table(name="DEPARTMENTS")
Public class Department{

   @Id
   @GeneratedValue
   Private long id;

   @Column(unique=true)
   Private String name;


   @ManyToOne(fetch = FetchType.EAGER)
   private Organization organization;

}
organizationRepository.deleteById(orgId);
@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@Transactional
public class OrganizationRepositoryTests {

    @Autowired
    private OrganizationRepository organizationRepository;

    @Autowired
    private DepartmentRepository departmentRepository;



    @Test
    public void testDeleteOrganization() {
        final organization organization = organizationRepository.findByName(organizationName).get(); //precondition

        Department d1 = new Department();
        d1.setName("d1");

        d1.setorganization(organization);

        Department d2 = new Department();
        d2.setName("d2");

        d2.setorganization(organization);

        departmentRepository.save(d1);
        departmentRepository.save(d2);

//        assertEquals(2, organizationRepository.getOne(organization.getId()).getDepartments().size()); //this assert is failing. For some reason organizations does not have a list of departments

        organizationRepository.deleteById(organization.getId());

        assertFalse(organizationRepository.findByName(organizationName).isPresent());
        assertEquals(0, departmentRepository.findAll().size()); //no departments should be found

    }

}

共有1个答案

鲁波光
2023-03-14

有关失败原因,请参阅代码注释:

@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@Transactional
public class OrganizationRepositoryTests {

    @Autowired
    private OrganizationRepository organizationRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @PersistenceContext
    private Entitymanager em;

    @Test
    public void testDeleteOrganization() {
        Organization organization = 
                organizationRepository.findByName(organizationName).get(); 

        Department d1 = new Department();
        d1.setName("d1");
        d1.setOrganization(organization);

        Department d2 = new Department();
        d2.setName("d2");
        d2.setOrganization(organization);

        departmentRepository.save(d1);
        departmentRepository.save(d2);

        // this fails because there is no trip to the database as Organization 
        // (the one loaded in the first line)
        // already exists in the current entityManager - and you have not 
        // updated its list of departments.
        // uncommenting the following line will trigger a reload and prove 
        // this to be the case: however it is not a fix for the issue.

        // em.clear();

         assertEquals(2,
             organizationRepository.getOne(
               organization.getId()).getDepartments().size()); 

        //similary this will execute without error with the em.clear() 
        //statement uncommented
        //however without that Hibernate knows nothing about the cascacding 
        //delete as there are no departments
        //associated with organisation as you have not added them to the list.
        organizationRepository.deleteById(organization.getId());

        assertFalse(organizationRepository.findByName(organizationName).isPresent());
        assertEquals(0, departmentRepository.findAll().size()); 
    }
}

正确的修复方法是通过封装add/remove/set操作和阻止对集合的直接访问来确保内存中的模型始终得到正确维护。例如。

public class Department(){
    public void setOrganisation(Organisation organisation){
        this.organisation = organisation;

        if(! organisation.getDepartments().contains(department)){
            organisation.addDepartment(department);
        }
    }
}

public class Organisation(){

    public List<Department> getDepartments(){
        return Collections.unmodifiableList(departments);
    }

    public void addDepartment(Department departmenmt){
        departments.add(department);

        if(department.getOrganisation() != this){
            department.setOrganisation(this);
        }
    }
}
 类似资料:
  • 我尝试使用r2dbc执行批处理插入。 我已经看到,使用spring boot中的DatabaseClient,这还不可能实现。我尝试使用R2DBC SPI语句和and方法来实现这一点,如下所示: 我在日志上看到完成了两个插入请求。 添加是执行批更新还是只运行两个请求? 谢谢

  • 作为测试的一部分,我一直在尝试创建一个用户,然后将其删除,但我不断收到相同的错误组织。冬眠hql。内部的QueryExecutionRequestException:即使在我的存储库和控制器中不断更改代码之后,DML操作也不受支持。 这是我的存储库中的代码: 这是我的控制器中的代码:

  • 我有Java控制器: 并遇到以下问题:警告14068--[nio-8080-exec-3].w.s.m.s.defaultHandlerExceptionResolver:Resolved[org.springframework.web.httpRequestMethodNotSupportedException:Request method'DELETE'not support]它发生在我发送删

  • Pandas 0.18支持读取csv zip文件作为参数,并将压缩的csv表正确读取到数据帧中。但当我试图使用to_csv()方法将数据帧保存为压缩的csv时,我遇到了错误。根据官方文档,to_csv()方法不支持zip格式。有什么想法吗?非常感谢。 作为pd进口熊猫 工作正常 数据=pd。阅读csv(“E:\ASML SED.zip”) error out IOError:[Errno 2]没有

  • 我正在使用spring boot(后端)和angulars js(前端),以及使用restful web服务在两个前端之间进行通信。这是我的Rest服务: 这是我的函数angulars js: 但是当点击删除按钮时,我得到了这个错误: 不支持DELETE方法????

  • 问题内容: 这在Microsoft SQL Server的T-SQL上是有效的语法,但在SQLite中则无效,在SQLite中是否有相同的替代语法? 问题答案: 通常,将整个联接移到一个子查询中,该子查询查找要删除的行的主键: 如果您有复合主键,则可以使用rowid代替: 如果您有复合主键,并且将该表创建为WITHOUT ROWID 表,则必须将联接重写为相关子查询: