【问题标题】:JPA manytomany unidirectional mappingJPA 多对多单向映射
【发布时间】:2011-03-14 15:14:36
【问题描述】:

我有两个类:ExternalTask​​ 和 ExternalSource。 ExternalTask​​ 有一个 ExternalSource 列表以及从 ExternalTask​​ 到 ExternalSource 的多对单向关系。

当我想删除一个 ExternalSource 时,我会检查它是否被任何 ExternalTask​​ 引用。如果是这样,我检查这个 ExternalTask​​ 是否在它的 List 中只有这个 externalsource。如果是我完全删除 ExternalTask​​;否则,我从列表中删除这个外部源并合并外部任务。然后我删除外部资源。但是,这违反了约束。我尝试使用无级联、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();
        }

        ...
    }

【问题讨论】:

  • 您确定违规是由externalSource 造成的,而不是由archives 造成的吗?
  • constraint name null 所以我不确定它的来源可能是存档的结果,但是为什么存档会导致这样的事情我不认为是因为存档。
  • 事实上,当不存在级联时,我不知道连接表会发生什么。任何人都知道休眠如何处理连接表。

标签: hibernate jpa many-to-many


【解决方案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
}

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2018-02-26
    • 2021-02-21
    • 2015-07-02
    • 2020-01-06
    相关资源
    最近更新 更多