代码之家  ›  专栏  ›  技术社区  ›  Kamil W

SpringData crudepository应用于自动级联类型

  •  0
  • Kamil W  · 技术社区  · 6 年前

    在我的项目中,我必须连接到现有的数据库并执行更新两个表的逻辑。

    @Entity
    @Table(name = "DOCUMENTCONTENT")
    @Getter
    public class DocumentContent {
    
        @Id
        @Column(name = "ID", insertable = false, updatable = false)
        private Long id;
    
        @OneToOne
        @JoinColumn(name = "DOCUMENT_ID", insertable = false, updatable = false)
        private Document document;
    
        @Lob
        @Column(name = "CONTENT")
        @Setter
        private byte[] content;
    }
    
    @Entity
    @Table(name = "DOCUMENT")
    @Getter
    public class Document {
    
        @Id
        @Column(name = "ID", insertable = false, updatable = false)
        private Long id;
    
        @OneToOne(mappedBy = "document")
        private DocumentContent documentContent;
    
        @OneToMany(mappedBy = "document", fetch = EAGER)
        private List<Attachment> attachments;
    }
    
    @Entity
    @Table(name = "ATTACHMENT")
    @Getter
    public class Attachment {
    
        @Id
        @Column(name = "ID")
        private Long id;
    
        @ManyToOne
        @JoinColumn(name = "DOCUMENT_ID", insertable = false, updatable = false)
        private Document document;
    
        @ManyToOne
        @JoinColumn(name = "CONTRACT_ID",updatable = false, insertable = false)
        private Contract contract;
    }
    
    @Entity
    @Table(name = "CONTRACT")
    @Getter
    public class Contract {
    
        @Id
        @Column(name = "ID", insertable = false, updatable = false)
        private Long id;
    
        @Column(name = "STATUS")
        @Setter
        private String status;
    
        @ManyToOne
        @JoinColumn(name = "CUSTOMER_ID", insertable = false, updatable = false)
        private Customer customer;
    
        @OneToMany(mappedBy = "contract", fetch = EAGER)
        private List<Attachment> attachments;
    }
    
    @Service
    public class MyServiceImpl implements MyService {
    
        @Autowired
        private DocumentContentRepository documentContentRepository; // spring data Crud Repository
    
        @Override
        @Transactional
        public void updateDocumentContent(SomeDto someDto) {
            DocumentContent documentContent = documentContentRepository.findByDocumentId(someDto.getDocumentId());
            documentContent.setContent(someDto.getBytes());
            List<Contract> contracts = documentContent.getDocument().getAttachments()
                    .stream().map(Attachment::getContract).collect(toList());
            contracts.forEach(contract -> contract.setStatus("SIGNED"));
            documentContentRepository.save(documentContent);
        }
    }
    

    当我从上述服务启动方法时,我可以注意到控制台输出中的SQL:

    休眠:更新documentcontent set content=?其中id=?

    我理解为什么jpa在documentcontent表中执行了第一次更新,但我不知道为什么它也在contract表中执行了更新。如你所见,我没有使用 CascadeType.MERGE 在任何实体中。

    你能解释一下为什么第二次更新没有声明级联类型吗?

    2 回复  |  直到 6 年前
        1
  •  1
  •   C. Weber    6 年前

    我怀疑它与级联有任何关系,但与事务性写后机制有关( more info

    documentContentRepository.save(documentContent);
    

    因为您正在修改两个托管实体。在事务结束时,hibernate保存所有被脏检查机制标记为已修改的实体( more info

        2
  •  1
  •   Yogi    6 年前

    您将收到第二个查询,原因是您正在修改合同的状态属性。

    这是@OneToMany的默认CaseCadeType行为

    进一步阅读请遵循以下内容 link