【问题标题】:How can I get information out of a junction table using JPA/EclipseLink?如何使用 JPA/EclipseLink 从联结表中获取信息?
【发布时间】:2010-10-27 03:14:31
【问题描述】:

我有以下多对多映射:

public class Student implements
{
    @Id
    @GeneratedValue
    private Integer xID;

@ManyToMany
@JoinTable(name = "x_y", 
           joinColumns = { @JoinColumn(name = "xID")},
           inverseJoinColumns={@JoinColumn(name="yID")})
private Set<Cat> cats;

}

公共类猫实现 { @ID @GeneratedValue 私有整数 yID;

@ManyToMany
@JoinTable(name = "x_y", 
           joinColumns = { @JoinColumn(name = "yID")},
           inverseJoinColumns={@JoinColumn(name="xID")})
private Set<Student> students;

}

请忽略对象和属性名称,它们是虚构的和不相关的。这可以编译并正常工作。我也可以这样做:

Entitymanager em = emf.createEntityManager();

em.getTransaction().begin(); 学生 s = new Student(); 学生 s2 = new Student(); 猫 c = 新猫(); em.persist(s); em.persist(s2); em.persist(c); s.getCats().add(c); c.getStudents().add(s2); em.getTransaction().commit();

当我从数据库中取回对象时,我的问题就出现了。

em.getTransaction().begin();
Student s = em.find(Student.class, 2);
Cat c = em.find(Cat.class, 3);

如果( c != null ) System.out.println(c.getYID() + ":" + c.getStudents()); 如果(小号!=空) System.out.println(s.getXID() + ":" + s.getCats()); em.getTransaction().commit();

打印输出是:

3: {IndirectSet: 未实例化}

2: {IndirectSet: 未实例化}

这很可能是正常行为。在我看来,当我从表中取回对象时,应该填充与其他对象相关的集合。我的意思是,因为联结表是这样的:

X |是的

2 | 3

1 | 3

em.find(Cat.class,3) 应该为 getStudents() 返回一个带有一组 {1,2} 的 Cat 对象,而 em.find(Student.class,2) 应该返回一个带有一组 {1,2} 的学生对象getCats() 的 {3}。

有什么办法可以做到吗?

谢谢, B.J.

【问题讨论】:

  • 您是手动滚动实体对象还是生成它们?应该为您的子对象设置设置器(例如 Cat 类中的 .setStudents() )。
  • 隐含了 getter 和 setter。我把它们放进去,我只是不想占用房间。我的代码编译并运行,但它并没有达到我的预期。

标签: java jpa persistence eclipselink entitymanager


【解决方案1】:

尝试将 @ManyToMany(cascade = CascadeType.ALL) 添加到您的 Cat 对象,以级联您的读取操作。

正确设置级联后,您可以将保存代码更改为;

Entitymanager em = emf.createEntityManager();

em.getTransaction().begin(); 
Student s = new Student(); 
Student s2 = new Student();
Cat c = new Cat();
// this should be c.setStudents(s2)
c.getStudents().add(s2); 
em.persist(c); 
em.getTransaction().commit(); 

老实说,你并不完全理解为什么要尝试将两个学生集分配给猫,你应该将两个集合并为一个,然后将它们添加到猫。

您可能还想明确设置您的提取类型,@ManyToMany(fetch = FetchType.LAZY) 或 FetchType.EAGER。

【讨论】:

    【解决方案2】:

    也许一个更好的例子是:

    em.getTransaction().begin(); 
    Student s = new Student(); 
    Student s2 = new Student(); 
    Cat c = new Cat(); 
    em.persist(s); 
    em.persist(s2);
    em.persist(c); 
    c.getStudents().add(s); 
    c.getStudents().add(s2); 
    em.getTransaction().commit(); 
    

    然后试着说

    Cat c2 = em.find(Cat.class,c.getYID());
    Student s3 = em.find(Student.class,s.getXID());
    System.out.println(c2.getYID() + ": " + c2.getStudents());
    System.out.println(s3.getXID() + ": " + s3.getCats());
    

    以上打印:

    1:{[[电影:movieID=2],[电影:movieID=3]]}

    2:{[]}

    这对我来说毫无意义,因为 id=1 的猫在其集合中具有 id=2 的电影,但 id=2 的电影在其集合中没有 id=1 的猫。 (更改级联类型似乎并没有影响结果。)

    非常感谢您的回复。

    B.J.

    【讨论】:

    • 看来,根据实体的设置方式,执行 c = em.find(Cat.class,1) 应该给我一个 cat 对象,其中包含所有行中的所有 XID在 YID 为 1 的 x_y 表中。基本上应该像这样说:c.setStudents(select XID from x_y where YID = 1;)
    • Benny,请注意,将来您可能希望编辑您的问题以添加说明或其他信息。
    • 这很奇怪,我建议您尝试从 Netbeans 生成类(我相信 eclipse 也可以这样做),而不是手动滚动它们。如果这不起作用,请返回并发布更多信息。
    猜你喜欢
    • 1970-01-01
    • 2021-11-21
    • 2011-03-12
    • 1970-01-01
    • 2020-03-10
    • 2015-06-02
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    相关资源
    最近更新 更多