Spring Data CrudRepository 自动应用级联类型
SpringData CrudRepository applies automaticlly cascade type
在我的项目中,我必须连接到现有数据库并执行更新两个 tables 的逻辑。
我的设置如下:
@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 在文档内容 table 中执行第一个更新,但我不知道为什么它在合同 table 中也执行更新。如您所见,我没有在任何实体中使用 CascadeType.MERGE
。
你能解释一下为什么在没有声明级联类型的情况下执行第二次更新吗?
在我的项目中,我必须连接到现有数据库并执行更新两个 tables 的逻辑。
我的设置如下:
@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 在文档内容 table 中执行第一个更新,但我不知道为什么它在合同 table 中也执行更新。如您所见,我没有在任何实体中使用 CascadeType.MERGE
。
你能解释一下为什么在没有声明级联类型的情况下执行第二次更新吗?