我有两个类:ExternalTask和ExternalSource。 ExternalTask有一个ExternalSource列表和从ExternalTask到ExternalSource的多种单向关系。
当我想删除ExternalSource时,我会检查它是否被任何ExternalTask引用。如果是这样,我检查这个ExternalTask是否在其List中只有这个externalsource。如果是我完全删除ExternalTask;否则,我从列表中删除此externalsource并合并externaltask。然后我删除externalsource。但是,这会违反约束条件。我尝试使用jointable没有cascade,cascadetype.update和cascadetype.refresh,但它仍然无法正常工作。有什么帮助吗?
这是删除方法:
public class Foo{
public boolean deleteExternalDataStorage(Long sid) {
EntityManager em = getEntityManager();
EntityTransaction et = em.getTransaction();
try {
et.begin();
ExternalDataStorage s = em.find(ExternalDataStorage.class, sid);
List<ExternalTask> tasks=(List<ExternalTask>) em.createQuery("SELECT t FROM ExternalTask t ").getResultList();
for(ExternalTask t:tasks) {
if(t.getExternalSources().contains(s)){
t.getExternalSources().remove(s);
if(t.getExternalSources().isEmpty()){
em.remove(t);
}else{
em.merge(t);
}
}
}
em.remove(s);
et.commit();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (et.isActive()) {
et.rollback();
}
}
return false;
}
}
@Entity
public class ExternalTask {
@ManyToMany
@JoinTable(name = "ExternalTask_ExternalSource", joinColumns = @JoinColumn(name = "TID"), inverseJoinColumns = @JoinColumn(name = "EXID"))
private List<ExternalDataStorage> externalSources=new ArrayList<ExternalDataStorage>();
@ManyToMany
@JoinTable(name = "ExternalTask_Archive", joinColumns = @JoinColumn(name = "TID"), inverseJoinColumns = @JoinColumn(name = "AID"))
protected List<Archive> archives=new ArrayList<Archive>();
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "TID")
protected Long id;
@NotNull
@Column(name = "name")
protected String name;
@Column(name = "description")
protected String description;
@Column(name="timeinterval" )
protected String interval;
@Column(name="startdate")
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
protected Date startDate;
...
}
@Entity
@Table(name = "ExternalSource")
public class ExternalDataStorage implements Serializable {
private static final long serialVersionUID = 3926424342696569894L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "EXID")
private Long id;
@NotNull
@Column(name = "NAME")
private String name;
@Column(name = "DESCRIPTION")
private String description;
@NotNull
@Column(name = "USERNAME")
private String username;
@Column(name = "PATH")
private String path;
@Column(name = "PORT")
private int port = 22;
@NotNull
@Column(name = "ISSECURE")
private boolean isSecure=true;
@NotNull
@Column(name = "ISINDEXINGENABLED")
private boolean indexingEnabled;
@Column(name = "INDEXINGREGEXP")
private String indexingRegExp = "({time}\\d{8}-\\d{6})";
@NotNull
@Column(name = "IP")
private String ip;
@Column
private String password;
@Column
private String protocol;
@Transient
private String publicKey;
@Column(name = "RSA_PRIV_KEY", length = 4096)
private String privateKey;
@Transient
private String regExpTestStr="";
@Transient
private boolean testSucced;
@Transient
private InputAddress inputAddr;
@Column
private boolean authenticationType;
@Column
private boolean timeStampingEnable=true;
@Column
private String sshPath;
@Column
private String filename="(.*\\.log)";
public ExternalDataStorage() {
inputAddr=new InputAddress();
}
...
}
答案 0 :(得分:1)
好的,你的任务和来源之间应该有双向的多对多关系。显然,根据您的要求,Source应该是关系中的拥有方,并且在Source端定义关系时不要使用CascadeType = All,而是在Task端使用它。如果你确实有双向关系,那么你就不必检查所有任务的整个列表。该部分代码是二次的,可以使用b方向映射轻松优化。此外,如果您在没有级联选项的情况下使Source成为拥有方,则依赖于Source以从任务中附加/分离自身。所以你需要做的就是:
if(source.getTaskList().size() == 1) {
//remove the task source.getTaskList().get(0), this will remove the source also
}
else {
//remove the source. The task is unaffected, as the source is the owning side
}