java - Spring Data CrudRepository 应用自动级联类型

标签 java spring hibernate jpa cascade

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

我的设置如下:

@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:

Hibernate: update documentcontent set content=? where id=?
Hibernate: update contract set status=? where id=?

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

您能解释一下为什么在没有声明级联类型的情况下执行了第二次更新吗?

最佳答案

我怀疑它与级联有任何关系,但与事务性写入机制( more info )有关。我相信你也可以摆脱这条线

documentContentRepository.save(documentContent);

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

关于java - Spring Data CrudRepository 应用自动级联类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52742939/

相关文章:

java - 使用 @OneToMany 或 @ManyToMany 来针对发生的未映射类异常

java - 是否可以在类级别为不同的数据类型配置 Jackson 自定义反序列化器?

java - 如何从 Spring Security 中删除过滤器?

hibernate - 当repository.save时Spring Boot + JPA + Hibernate不提交

mysql - 反向子句 IN 命名查询 Hibernate

使用 FileWriter 的 java.lang.NullPointEreException

java - 如何记录一个接口(interface)所有实现的每个方法的时间成本

java - 为什么我的 Eclipse 插件 ICommand IParameter 的值没有出现在 Preferences/Keys 设置中?

java - spring标签中是否存在输入类型="date"的模拟?

java - Spring JPA NoRepositoryBean 查询