有没有办法删除@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?

查看:441
本文介绍了有没有办法删除@OneToMany关系中的子实体(使用JoinTable),而无需获取完整的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  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是否提供其他更好的解决方案?解决方案

- 你可以为连接表创建一个实体类。



你必须在 @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);


I've got the following classes/relationship (getters & setters not displayed, but present):

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;
}

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

}

The class 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
}

Now you can remove a single entry in join table and even cause attachment object to be deleted too.

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);

这篇关于有没有办法删除@OneToMany关系中的子实体(使用JoinTable),而无需获取完整的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆