如何使用JPA设置递归的多对多关系,并带有关联类?

huangapple go评论78阅读模式
英文:

How do I set up a recursive, many-to-many relationship WITH an association class using JPA?

问题

因此,我正在尝试创建一个药店数据库,其中包括对药物间相互作用进行跟踪的功能,除其他内容外。我有一个Drug实体,其中包含各种成员和关联,到目前为止,它们似乎都运行良好。我不确定我是否正确实现了与Drug实体具有递归的多对多关系的一个实现,该实现使用了一个关联类。关联类(DrugDrugIX)有2个外键 - 分别来自每种药物 - 以及相互作用的描述和严重程度的分配。

我到目前为止所做的是可以工作的,编译和运行都没有问题,我可以添加药物和相互作用。然而,我肯定认为我所做的不是最优的 - 甚至可能不正确。关于如何优化我所尝试做的事情,有什么建议吗?

Drug 实体(为简洁起见省略了一些成员):

@Entity
@Table(name = "drugs")
@NamedQueries({
        @NamedQuery(name = Drug.FIND_ALL_BY_NAME,
                     query = "SELECT d FROM Drug d WHERE LOWER(d.chemical_name) LIKE LOWER(CONCAT('%', :searchString, '%'))")
})
public class Drug {
    // 查询字符串
    public static final String FIND_ALL_BY_NAME = "Drug.findAllByName";

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long did;

    private String chemical_name;
    private String description;

    // 关联
    <------------------------>
    @OneToMany(mappedBy = "base", cascade = CascadeType.PERSIST)
    private List<DrugDrugIX> interxAsBase;
    
    @OneToMany(mappedBy = "offender", cascade = CascadeType.PERSIST)
    private List<DrugDrugIX> interxAsOffender;
    <------------------------>

    @ManyToOne(cascade = CascadeType.PERSIST)
    private DEA_Class schedule;

    @OneToOne(cascade = CascadeType.PERSIST)
    private Pharmacology PK_profile;

    (...) 这里是其他关联getter和setter (...)

    public void addInterxAsBase(DrugDrugIX interaction) {
        if (this.interxAsBase == null)
            interxAsBase = new ArrayList<>();

        interxAsBase.add(interaction);
    }

    public void addInterxAsOffender(DrugDrugIX interaction) {
        if (this.interxAsOffender == null)
            interxAsOffender = new ArrayList<>();

        interxAsOffender.add(interaction);
    }
}

DrugDrugIX 关联实体:

@Entity
@Table(name = "drug_drug_interactions")
public class DrugDrugIX {
    @EmbeddedId
    private DrugDrugIX_PK interaction_CPK;
    private int severityLevel = -1;
    
    // 关联
    @ManyToOne
    @MapsId("base")
    private Drug base;
    
    @ManyToOne
    @MapsId("offender")
    private Drug offender;

    (...) 为简洁起见省略了getter和setter (...)

    public void registerInteraction(Drug object, Drug precipitate) {
        if (this.base == null)
            this.base = object;
        if (this.offender == null)
            this.offender = precipitate;

        if ((this.base == object && this.offender == precipitate) && (severityLevel == -1)) {
            object.addInterxAsBase(this);
            precipitate.addInterxAsOffender(this);
        }
    }
}

... 为了记录,组成DrugDrugIX实体主键的Embeddable:

@Embeddable
public class DrugDrugIX_PK implements Serializable {
    private long base;
    private long offender;
    private String description;

    // 构造函数
    public DrugDrugIX_PK() {}
    public DrugDrugIX_PK(Drug base, Drug offender, String description) {
        this.base = base.getDID();
        this.offender = offender.getDID();
        this.description = description;
    }
    
    // 访问器
    public String getDescription() { return this.description; }

    // 其他
    @Override
    public boolean equals(Object other) {
        if (other instanceof DrugDrugIX_PK) {
            DrugDrugIX_PK second = (DrugDrugIX_PK) other;

            return (this.base == second.base) && (offender == second.offender) && (this.description.equals(description));
        } else
            return false;
    }

    @Override
    public int hashCode() { return (int) (base + offender); }
}

我为你指引的方向是这样的。

英文:

So I'm trying to create a pharmacy database that, among other things, keeps track of drug-to-drug interactions. I have a Drug entity with various members and associations and they all seem to work out fine thus far. The one implementation I'm not sure I have down correct is a recursive, many-to-many relationship with the Drug entity using an association class. The association class (DrugDrugIX) has 2 foreign keys - one from each drug - and a description and assignment of how severe is that interaction.

What I have so far works, in that it will compile and run and let me add Drugs and interactions. However, I certainly don't think what I'm doing is the most optimal -- or even correct. Any advice on how to optimize what I'm trying to do?

The Drug entity (some members omitted for brevity):

@Entity
@Table (name = &quot;drugs&quot;)
@NamedQueries({
@NamedQuery (name = Drug.FIND_ALL_BY_NAME,
query = &quot;SELECT d FROM Drug d WHERE LOWER (d.chemical_name) LIKE LOWER (CONCAT (&#39;%&#39;, :searchString, &#39;%&#39;))&quot; )
})
public class Drug
{
// QUERY STRING(S)
public static final String FIND_ALL_BY_NAME = &quot;Drug.findAllByName&quot;;
@Id
@GeneratedValue (strategy = GenerationType.IDENTITY)
private long did;
private String chemical_name;
private String description;
// ASSOCIATION(S)
is this the correct implementation (???)
&lt;-----------------------------------------------------------------------------------&gt;
@OneToMany (mappedBy = &quot;base&quot;, cascade = CascadeType.PERSIST)
private List&lt;DrugDrugIX&gt; interxAsBase;
@OneToMany (mappedBy = &quot;offender&quot;, cascade = CascadeType.PERSIST)
private List&lt;DrugDrugIX&gt; interxAsOffender;
&lt;-----------------------------------------------------------------------------------&gt;
@ManyToOne (cascade = CascadeType.PERSIST)
private DEA_Class schedule;
@OneToOne (cascade = CascadeType.PERSIST)
private Pharmacology PK_profile;
(...) other associations, getters and setters here (...)
public void addInterxAsBase (DrugDrugIX interaction)
{
if (this.interxAsBase == null)
interxAsBase = new ArrayList&lt;&gt;();
interxAsBase.add (interaction);
}
public void addInterxAsOffender (DrugDrugIX interaction)
{
if (this.interxAsOffender == null)
interxAsOffender = new ArrayList&lt;&gt;();
interxAsOffender.add (interaction);
}
}

The DrugDrugIX association entity:

@Entity
@Table (name = &quot;drug_drug_interactions&quot;)
public class DrugDrugIX
{
@EmbeddedId
private DrugDrugIX_PK interaction_CPK;
private int severityLevel = -1;
// ASSOCIATION(S)
@ManyToOne
@MapsId (&quot;base&quot;)
private Drug base;
@ManyToOne
@MapsId (&quot;offender&quot;)
private Drug offender;
(...) getters, setters omitted for brevity (...)
public void registerInteraction (Drug object, Drug precipitate)
{
if (this.base == null)
this.base = object;
if (this.offender == null)
this.offender = precipitate;
if ((this.base == object &amp;&amp; this.offender == precipitate) &amp;&amp; (severityLevel == -1))
{
object.addInterxAsBase(this);
precipitate.addInterxAsOffender(this);
}
}
}

...and just for posterity, the Embeddable that comprises the primary key of the DrugDrugIX entity:

@Embeddable
public class DrugDrugIX_PK implements Serializable
{
private long base;
private long offender;
private String description;
// CONSTRUCTORS
public DrugDrugIX_PK () {}
public DrugDrugIX_PK (Drug base, Drug offender, String description)
{
this.base = base.getDID();
this.offender = offender.getDID();
this.description = description;
}
// ACCESSORS
public String getDescription () { return this.description; }
// MISCELLANEOUS
@Override
public boolean equals (Object other)
{
if (other instanceof DrugDrugIX_PK)
{
DrugDrugIX_PK second = (DrugDrugIX_PK) other;
return (this.base == second.base) &amp;&amp; (offender == second.offender) &amp;&amp; (this.description.equals (description));
}
else
return false;
}
@Override
public int hashCode () { return (int) (base + offender); }
}

I pray to the stackoverflow gods for guidance..

答案1

得分: 1

以下是翻译好的内容:

你不需要使用递归,只需使用两个嵌套循环。类似这样的伪代码:

int[] drugs = {1, 4, 6};
for (i=0; i<drugs.length; i++) {
    drug1 = drugs[i];
    for (int j=i+1; j<drugs.length; j++) {
         drug2 = drugs[j];
         get_interaction(drug1, drug2);
    }
}

药物的管理通过整数在药物数组中表示。

英文:

You do not need to use recursion. Just use two nested loops. Something like this pseudo code:

int[] drugs = {1, 4, 6};
for (i=0; i&lt;drugs.length; i++) {
drug1 = drugs[i];
for (int j=i+1; j&lt;drugs.length; j++) {
drug2 = drugs[j];
get_interaction(drug1, drug2);
}
}

Drugs being administered are represented by integers in the drugs array.

huangapple
  • 本文由 发表于 2020年7月26日 09:21:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/63095204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定