有没有办法删除@OneToMany关系中的子实体(使用JoinTable),而无需获取完整的集合? [英] Is there a way to delete a child entity in a @OneToMany relationship (with a JoinTable) without having to fetch the full collection?
问题描述
public class Contract implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =id)
private Long id;
@版本
@Column(name =version)
私有整数版本;
私人字符串编号;
私有字符串卷;
@OneToMany(cascade = CascadeType.REMOVE)
@JoinTable(joinColumns = @JoinColumn(name =contract_id,referencedColumnName =id),inverseJoinColumns = @JoinColumn(name = attachment_id,referencedColumnName =id))
private List< Attachment>附件;
public class Attachment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =id)
私人长ID;
@版本
@Column(name =version)
私有整数版本;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(length = 2147483647)
private byte [] contents;
私人字符串名称;
}
根据我的需求/设计,我正在使用连接表。 p>
如果我想从合同中删除一个附件,我需要加载合同,然后遍历所有附件,直到找到想要删除的附件从列表中。
虽然这是功能性的,但它需要很多数据库通信。如果附件列表很长,并且包含大量内容,它还需要很大的带宽。
有没有其他办法可以删除它?如果我试图直接删除附件(例如:Attachment.findById()。delete()),它将因FK关系而失败 - 不是吗? (我还没有尝试过,但我怀疑它)。
另外,如果我有一个非常大的附件列表,逐个遍历它们,直到找到正确的附件也不是非常有效。 b
$ b
JPA是否提供其他更好的解决方案?解决方案
- 你可以为连接表创建一个实体类。
你必须在 类 现在,您可以删除连接表中的单个条目,甚至还可以删除附件对象。 I've got the following classes/relationship (getters & setters not displayed, but present): As per my needs/design, I am using a join table. If I want to delete an attachment from the Contract, I need to load the Contract, and then loop through all the attachments until I find the one I want to remove and remove it from the list. Although this is functional, it will require a lot of DB communication. If the list of attachments is long, and contains large contents, it will also require large bandwidth. Is there any other way I can remove it? If I try to remove the attachment directly (ex: Attachment.findById().delete()), it will fail due to the FK relationship - won't it? (I haven't tried this yet, but I suspect it). Additionally, if I have a very large list of attachments, iterating through them one by one until I find the correct one is not very efficient either. Does JPA provide any other/better solution? There's one workaround solution I know - you can create an entity class for join table. You will have to give a name to your join table within The class Now you can remove a single entry in join table and even cause attachment object to be deleted too.
这篇关于有没有办法删除@OneToMany关系中的子实体(使用JoinTable),而无需获取完整的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! @JoinTable
注解( name 属性),可以说 ContractAttachment
。然后你可以创建实体:
$ $ p $ @Entity(name =ContractAttachment)//注意同名的表
@IdClass(ContractAttachmentId.class)
public class ContractAttachment实现Serializable {
static final long serialVersionUID = 1L;
@Id
@ManyToOne
@JoinColumn(name =contract_id)//相同的列映射
私有合约;
@Id
@ManyToOne(cascade = CascadeType.REMOVE)
@JoinColumn(name =attachment_id)//列的相同映射
私有附件附件;
//你还必须在这里覆盖equals和hashcode方法
$ / code> ContractAttachmentId
应该如下所示:
public class ContractAttachmentId实现Serializable {
私人长期合约; //注意相同的字段名称
私有长附件;
//这个类也应该实现hashcode并且等于
}
ContractAttachment ca = em .createQuery(从ca选择ca+
其中ca.contract =:contract和ca.attachment =:attachment)
.setParameter(contract,selectedContract)
。 setParameter(attachement,selectedAttachment)
.getSingleResult();
em.remove(ca);
public class Contract implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Version
@Column(name = "version")
private Integer version;
private String number;
private String volume;
@OneToMany(cascade=CascadeType.REMOVE)
@JoinTable(joinColumns = @JoinColumn(name = "contract_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "attachment_id", referencedColumnName = "id"))
private List<Attachment> attachments;
}
public class Attachment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Version
@Column(name = "version")
private Integer version;
@Lob
@Basic(fetch=FetchType.LAZY)
@Column(length=2147483647)
private byte[] contents;
private String name;
}
@JoinTable
annotation (name attribute), lets say ContractAttachment
. Then you can create entity:@Entity(name = "ContractAttachment") // note the same name of table
@IdClass(ContractAttachmentId.class)
public class ContractAttachment implements Serializable {
static final long serialVersionUID = 1L;
@Id
@ManyToOne
@JoinColumn(name="contract_id") // same mappings for columns
private Contract contract;
@Id
@ManyToOne(cascade = CascadeType.REMOVE)
@JoinColumn(name="attachment_id") // same mappings for columns
private Attachment attachment;
// you will also have to override equals and hashcode methods here
}
ContractAttachmentId
should look like:public class ContractAttachmentId implements Serializable {
private long contract; // note the same fields names
private long attachment;
// this class should also implement hashcode and equals
}
ContractAttachment ca = em.createQuery("select ca from ContractAttachment ca " +
"where ca.contract = :contract and ca.attachment = :attachment")
.setParameter("contract", selectedContract)
.setParameter("attachement", selectedAttachment)
.getSingleResult();
em.remove(ca);