简体   繁体   English

仅使用ID字段为联接表创建JPA带注释的实体

[英]creating JPA annotated entity for join table using only the ID fields

I'm trying to figure out a cleaner way of saving a join table back to the database using only the entity id of the two joined tables. 我试图找出一种更清洁的方法,仅使用两个联接表的实体ID将联接表保存回数据库。 I can make my code work as is, but I feel like there should be a cleaner manner. 我可以按原样运行代码,但是我觉得应该有一种更简洁的方式。

Imagine I have an entity which represents a simple sql join table, so something like this: 想象一下,我有一个代表简单sql连接表的实体,所以像这样:

@Entity
@Table(name = "FOOBAR")
public class FooBar{

    @ManyToOne(fetch = FetchType.Lazy)
    @JoinColumn(name = "FOO_ID)
    public Foo foo;

    @ManyToOne(fetch = FetchType.Lazy)
    @JoinColumn(name = "BAR_ID)
    public Bar bar;

    public FooBar(Foo foo, Bar bar){
       this.foo=foo;
       this.bar=bar;
    }
}

I have a method which takes a Foo id and a Bar id, and wants to pass a FooBar object to my save method to save the join. 我有一个方法,该方法带有Foo ID和Bar ID,并且想要将FooBar对象传递给我的save方法以保存联接。

A naive implementation would query the database to find the Foo and Bar objects based off of their ids, pass those into the FooBar constructor, and then pass the new FooBar to the save method. 一个幼稚的实现将查询数据库以根据其id查找Foo和Bar对象,将它们传递给FooBar构造函数,然后将新的FooBar传递给save方法。

However, this is silly, the only things my join table needs is the foo and bar ids, not the full DB objects. 但是,这很愚蠢,我的联接表唯一需要的是foo和bar id,而不是完整的DB对象。 I have everything I need already without hitting the DB to fetch Foo and Bar. 我已经拥有了我所需的一切,而无需访问数据库来获取Foo和Bar。

In fact I could simply construct a Foo object and bar object using their a public ID, ignoring all the other fields of the objects, create a FooBar object from these two 'empty' foo and bar objects, and pass that to save and it would work just fine without extra DB hits. 实际上,我可以简单地使用它们的公共ID构造Foo对象和bar对象,而忽略这些对象的所有其他字段,从这两个“空” foo和bar对象创建一个FooBar对象,并将其传递给保存,它将工作正常,没有额外的数据库命中。

However, it somehow feels a little unclean to do this. 但是,这样做有点不干净。 I'm creating two 'dummy' objects this way. 我正在以这种方式创建两个“虚拟”对象。 My foo and bar objects may have some nullable = false columns which my DB contract promises will never be null, so it feels wrong constructing a foo object that does have null fields for these columns; 我的foo和酒吧对象可能有一些可为空=虚假列这我DB合同承诺永远不会为空,所以感觉错了构建一个Foo对象确实有这些列空字段; as if I'm breaking the contract for these objects. 好像我要破坏这些对象的合同一样。 I don't want a constructor for either object that accepts only an ID because; 不想为仅接受ID的任何一个对象构造函数,因为; I want to force them to be constructed in a manner that abides by my contract any time someone constructs them. 我想强迫他们以任何人建造它们时都遵守我的合同的方式建造。 I would prefer not to have to knowingly create objects that violate my promise. 我宁愿不必故意创建违反我诺言的对象。

I'm wondering if there is a way through JPA, or some quickly written abstraction I could do, to build my FooBar object using only the foo and bar ids in a way that is clean and communicative and does not violate any of the Foo/Bar constraints. 我想知道是否有一种通过JPA的方法,或者我可以做的一些快速编写的抽象方法,以仅使用foo和bar id的方式构建我的FooBar对象,这种方式是干净且可交流的, 并且不违反任何Foo /酒吧约束。 After all since both Foo and Bar are lazy loaded when I first get a FooBar object all it really contains are the foo and bar ids until I call the getter; 毕竟,当我第一次获得FooBar对象时,Foo和Bar都是延迟加载的,它真正包含的都是foo和bar id,直到我调用getter为止。 so I contain as much information already as a FooBar object from the DB would have. 所以我已经包含了数据库中FooBar对象所拥有的尽可能多的信息。

can I create a FooBar object with only their ID and have that object tied to the DB, so it would lazy load the Foo and Bar objects if the getter were called just like a FooBar I get from the DB does? 是否可以创建仅具有其ID的FooBar对象并将该对象绑定到数据库,因此如果调用getter就像从数据库中获取的FooBar一样,它将延迟加载Foo和Bar对象?

The entityManager#getReference seems to be what you are looking for. entityManager#getReference似乎是您想要的。 It creates and returns an object that can be used wherever a reference to an entity is required and can (but in your case, will not have to) have all its state fetched lazily. 它创建并返回一个对象,该对象可以在需要引用实体的任何地方使用,并且可以(但在您的情况下,则不必)延迟获取其所有状态。

Having a class for a join table is overkill. 为联接表创建一个类是过大的。

JPA has the ManyToMany annotation, which creates the relationship for you. JPA具有ManyToMany批注,该批注为您创建关系。

You basically need to choose one of the entities to "own" the relationship. 您基本上需要选择一个实体来“拥有”该关系。 This is more or less which class defines the table being used for the join. 这或多或少是由哪个类定义用于联接的表。

In this case, I'll choose Foo as the one that owns the relationship. 在这种情况下,我将选择Foo作为拥有该关系的人。

In Foo , you can do this: Foo ,您可以执行以下操作:

@ManyToMany
@JoinTable(name="FOOBAR", joinColumns=@JoinColumn(name="FOO_ID"),
    inverseJoinColumns=@JoinColumn(name="BAR_ID"))
public Set<Bar> bars;

and in Bar : Bar

@ManyToMany(mappedBy="bars")
public Set<Foo> foos;

Note, although I used Set , you can use List instead. 注意,尽管我使用Set ,但是您可以使用List

Note: ManyToMany is Lazy by default... and I suggest leaving it that way. 注意:默认情况下, ManyToMany是惰性的...,我建议您采用这种方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM