当前位置: 首页 > 知识库问答 >
问题:

Hibernate(4.1.2)和Spring(3.1.2)-ManyToMany关系不将记录存储在JoinTable中

淳于烈
2023-03-14

我有一个问题,需要你的帮助来解决这个问题。希望这篇文章能成为类似问题的参考…

在我最小化的商业模式中,有用户和标题。应该首先创建标题,并且可以分配给许多用户,并且用户可能共享相同的标题。因此,我创建了两个名为User和Title的实体,它们具有@ManyTomany关系,并决定Title应该拥有这个关系。另外,我有一个UnitTest来运行这个示例。

public class User {

    Long id;
    String name;
    Set<Title> titles = new HashSet<Title>();

    @Id
    @GeneratedValue
    @Column(name = "id")    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    /*============ Approach1 ============*/
//  @ManyToMany(mappedBy = "users")
    /*============ Approach2 ============*/
//  @ManyToMany
    /*============ Approach3 ============*/
    @ManyToMany
    @JoinTable( name = "tb_title_user",
                joinColumns = @JoinColumn(name = "user_id"),
                inverseJoinColumns = @JoinColumn(name = "title_id"))
    public Set<Title> getTitles() {
        return titles;
    }
    public void setTitles(Set<Title> titles) {
        this.titles = titles;
    }

}
public class Title {

    Long id;
    String description;
    Set<User> users = new HashSet<User>();


    @Id
    @GeneratedValue
    @Column(name = "id")    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "description")
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    /*============ Approach1 & Approach2 & Approach3 ============*/
    @ManyToMany
    @JoinTable( name = "tb_title_user",
                joinColumns = @JoinColumn(name = "title_id"),
                inverseJoinColumns = @JoinColumn(name = "user_id"))
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }
}

单位测试

public class UserTest {

    @Autowired
    private SessionFactory sessionFactory;


    @Test
    @Rollback(false)
    @Transactional
    public void saveUser(){
        Session session = sessionFactory.getCurrentSession();
        String now = new Date().toString();

        Title title = new Title();
        title.setDescription("TitleDescription: " + now);
        session.save(title);

        User user = new User();
        user.setName("UserName: " + now);
        user.getTitles().add(title);

        session.saveOrUpdate(user);
    }

}

如果您查看上面的代码,您将看到三种不同的方法。如果数据正确地存储在数据库表中,将在下面进行描述:

             Title      User     JoinTable
Approach1    Yes        Yes      No
Approach2    Yes        Yes      Yes
Approach3    Yes        Yes      Yes

以下是我对每种方法的看法:

“如前所述,另一方不必(必须不)描述物理映射:包含所有者端属性名的简单mappedBy参数将两者绑定。”

如果我理解正确的话,我就不必(一定不能)在用户实体中添加@Jointable。

接近2

共有1个答案

红砚文
2023-03-14

唯一正确的方法是第一条:

@ManyToMany(mappedBy = "users")
public Set<Title> getTitles() {
    return titles;
}

...

@ManyToMany
@JoinTable(name = "tb_title_user",
           joinColumns = @JoinColumn(name = "title_id"),
           inverseJoinColumns = @JoinColumn(name = "user_id"))
public Set<User> getUsers() {
    return users;
}

反向方使用mappedby属性表示:“我是反向方。请查看目标实体中的users属性,查看此关联是如何映射的。”

您做错的是,在测试中只修改了相反的一面。JPA/Hibernate只考虑所有者一方知道关联是否存在。所以与其做

user.getTitles().add(title);
title.getUsers().add(user);

我真的希望这一步能成为类似问题的参考,但我对此表示怀疑,因为我已经回答了无数次这个问题,而且这个问题一次又一次地出现,尽管在文档中有清楚的解释:

如果关联是双向的,则一方必须是所有者,一方必须是反向端(即更新关联表中的关系值时会忽略它):

[下面是一个示例,在双向多对多关联的每一侧都有适当的注释]

 类似资料:
  • 问题内容: 我有问题,需要您的帮助来解决此问题。希望这一步可能成为类似问题的参考。 在我最小化的业务模型中,有用户和标题。应该首先创建标题,并且可以将其分配给许多用户,并且用户可以共享相同的标题。因此,我创建了两个具有@ManyToMany关系的名为User和Title的实体,并确定Title应该拥有该关系。另外,我有一个UnitTest来运行此示例。 用户实体 标题实体 单元测试 如果看上面的代

  • 为了使问题变得简单,让我们假设我有一个具有三个属性的用户实体:id、email和一组角色(owner、@manytomany、@jointable)。我将合并至少具有一个或多个角色用户实体,而不通过EntityManager查找它: 数据库中的结果是:

  • 问题内容: 我下面有两个… 我想更新的,有时也用下面的方法有时… 方法#1 方法#2 第一种方法可以正常工作,但第二种则不能。但是,当我将“ 从” 移至“ 第二”方法时,效果很好,而不是第一个。 问题答案: 问题是一个问题。 假设它是的子类,那么您的问题是关系中只有一方是拥有实体。将使得实体所属的实体,因此仅改变该实体被持久化。这意味着,你必须更新在这两种情况下的实体。如果您有一个“ a”的组列表

  • 在一个项目中,我有以下实体:具有连接到关键字的模板部分的模板。这两种关系都是。一些代码: 然后,我尝试使用给定ID查找与某个模板相关的关键字。我使用使用此谓词执行此操作: 由于某些原因,谓词处理得根本不好。尝试调用方法时出现此错误: 组织.hibernate.hql.internal.ast.QuerySyntax 异常: 模板实体部分目录未映射 [选择关键字身份\nfrom mypackage.

  • 我想在(您可以将其视为Student)实体和实体之间实现一个@ManyTomany单向的。很简单,一个教室可以有很多学生,而学生可以有很多教室。我希望它是单向的,因为我希望班级只知道它包含什么学生,学生不必知道他们有什么班级。这就是我目前所拥有的: ClassRoom.java Account.java 我通过以下代码保存它(使用Spring JPA): 但我得到了以下错误: 下面是StackTr

  • 问题内容: 我有一些与关系有关的实体: 和 使用某些模型执行保存模型时,一切正常。表存储这些实体的所有键。但是,使用驱动程序保存模型时,表不会更改。我认为映射存在问题。 问题答案: 那是预期的行为。在双向多对多关联中,一侧必须是反侧。在您的情况下,这是一面,因为它包含: 拥有关系的字段。除非关系是单向的,否则为必需。 这意味着是关联的所有者,并且Hibernate仅在维护关联时检查该侧。