Java JPA多对多坚持加入表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19465662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 17:30:27  来源:igfitidea点击:

JPA many-to-many persist to join table

javasqljpaeclipselink

提问by erdoganonur

I have two table with many-to-many relations. I mapped this two entities when I am persisting users doesn't insert anything to join table. I am debugging till the persist, I see groups list is not null.

我有两个多对多关系的表。当我坚持用户不插入任何东西来连接表时,我映射了这两个实体。我正在调试直到坚持,我看到组列表不为空。

Ther is no error message just persist user.

没有错误消息只是坚持用户。

users <--> user-group <--> groups

用户 <--> 用户组 <--> 组

I am using netbeans 7.3, Glassfish 3.1.2.2, postgresql 9.1 and eclipselink 2

我使用的是 netbeans 7.3、Glassfish 3.1.2.2、postgresql 9.1 和 eclipselink 2

Also, I tried to show sql scripts that properties below doesn't work for me.

另外,我试图显示下面的属性对我不起作用的 sql 脚本。

        <property name="eclipselink.logging.logger" value="ServerLogger"/>
        <property name="eclipselink.logging.level" value="FINE"/>
        <property name="eclipselink.logging.level.sql" value="FINE"/>
        <property name="eclipselink.logging.parameters" value="true"/>

Abstact DAO:

抽象DAO:

public abstract class GenericDAO<E> implements Serializable{

@PersistenceContext
EntityManager entityManager;

public void persist(E object){
    entityManager.persist(object);
}

public void merge(E object){
    entityManager.merge(object);
}

public void delete(E object){
    object = entityManager.merge(object);
    entityManager.remove(object);
}
}

Users Entity :

用户实体:

   @Entity
@Table(name = "users")
@XmlRootElement
@NamedQueries(
{
    @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
    @NamedQuery(name = "Users.findByUserId", query = "SELECT u FROM Users u WHERE u.userId = :userId"),
    @NamedQuery(name = "Users.findByName", query = "SELECT u FROM Users u WHERE u.name = :name"),
    @NamedQuery(name = "Users.findBySurname", query = "SELECT u FROM Users u WHERE u.surname = :surname"),
    @NamedQuery(name = "Users.findByEmail", query = "SELECT u FROM Users u WHERE u.email = :email"),
    @NamedQuery(name = "Users.findByUsername", query = "SELECT u FROM Users u WHERE u.username = :username"),
    @NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")
})
public class Users implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "user_id")
    private Integer userId;
    @Size(max = 2147483647)
    @Column(name = "name")
    private String name;
    @Size(max = 2147483647)
    @Column(name = "surname")
    private String surname;
    // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
    @Size(max = 2147483647)
    @Column(name = "email")
    private String email;
    @Size(max = 2147483647)
    @Column(name = "username")
    private String username;
    @Size(max = 2147483647)
    @Column(name = "password")
    private String password;
    @ManyToMany(mappedBy = "usersList")
    private List<Groups> groupsList;
    @OneToMany(mappedBy = "userId")
    private List<Person> personList;

//Getters Setters

Groups Entity :

团体实体:

@Entity
@Table(name = "groups")
@XmlRootElement
@NamedQueries(
{
    @NamedQuery(name = "Groups.findAll", query = "SELECT g FROM Groups g"),
    @NamedQuery(name = "Groups.findByGroupId", query = "SELECT g FROM Groups g WHERE g.groupId = :groupId"),
    @NamedQuery(name = "Groups.findByGroupName", query = "SELECT g FROM Groups g WHERE g.groupName = :groupName"),
    @NamedQuery(name = "Groups.findByGroupDescription", query = "SELECT g FROM Groups g WHERE g.groupDescription = :groupDescription")
})
public class Groups implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "group_id")
    private Integer groupId;
    @Size(max = 2147483647)
    @Column(name = "group_name")
    private String groupName;
    @Size(max = 2147483647)
    @Column(name = "group_description")
    private String groupDescription;
    @JoinTable(name = "user_group", joinColumns =
    {
        @JoinColumn(name = "group_id", referencedColumnName = "group_id")
    }, inverseJoinColumns =
    {
        @JoinColumn(name = "user_id", referencedColumnName = "user_id")
    })
    @ManyToMany(fetch = FetchType.EAGER)
    private List<Users> usersList;
//Getters Setters

User DAO :

用户 DAO :

public class UserDAO extends GenericDAO<Users> implements Serializable {

    public List<Users> getAllUsers()
    {
        Query query = entityManager.createNamedQuery("Users.findAll");
        List<Users> users = query.getResultList();
        return users;
    }
}

回答by Ravi Thapliyal

You need to enable cascadefor merge (using PERSIST) or all operations with ALL.

您需要启用cascade合并(使用PERSIST)或使用ALL.

@ManyToMany(mappedBy = "usersList", cascade = CascadeType.PERSIST)
private List<Groups> groupsList;


If I set CascadeType.PERSIST, it insert data to groups table too. I want to add date users table and user_group table (pk_user, pk_group)

如果我设置 CascadeType.PERSIST,它也会将数据插入到组表中。我想添加日期用户表和用户组表(pk_user,pk_group)

The way a mapping/join table works is that user_groupwould have a foreign keyconstraint on userand grouptable. That's why a new row in grouphas to be inserted for its primary keyto be used to add a new row to user_group.

映射/连接表的工作方式是,user_group将有一个外键的约束usergroup表。这就是为什么group必须插入一个新行作为其主键才能用于将新行添加到user_group.

This has nothing to do with JPA and the same would apply to you even if you were using plain JDBC instead. This is how Entity-Relationshipswork in database.

这与 JPA 无关,即使您使用普通 JDBC,这也适用于您。这就是实体关系在数据库中的工作方式。

Also I dropped all tables and they were generated by eclipse link automatically. They are same but don't insert any row to 'user_group'.

我还删除了所有表,它们是由 eclipse 链接自动生成的。它们相同但不向“user_group”插入任何行。

This behaviour is controlled by the eclipselink.ddl-generationproperty specified for your persistence-unit. When specified as drop-and-create-tables, EclipseLink recreates the whole database schema (deleting any existing data in the process).

此行为由eclipselink.ddl-generation为您指定的属性控制persistence-unit。当指定为 时drop-and-create-tables,EclipseLink 将重新创建整个数据库模式(删除过程中的任何现有数据)。

<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>

This, however, is enabled just to ease your development. This isn't supposed to be used in production environments where its disabled by notspecifying this property or by setting its value as none.

然而,这只是为了简化您的开发。这不应该用于通过指定此属性或将其值设置为none.

<property name="eclipselink.ddl-generation" value="none"/>

回答by viejodecaldas

For your first question about to show sql scripts, i've added this code in the persistence.xml

对于关于显示 sql 脚本的第一个问题,我已在 persistence.xml 中添加了此代码

<properties>
  <property name="eclipselink.logging.level.sql" value="FINE"/>
  <property name="eclipselink.logging.parameters" value="true"/>
</properties>

After that, clean and build and then deploy. The sql executed by JPA will be displayed in the glassfish domain log of the netbeans.

之后,清理并构建然后部署。JPA执行的sql会显示在netbeans的glassfish域日志中。

For your second issue about the many-to-many relationship.

关于多对多关系的第二个问题。

i was having the same issue in the same scenario, beacuse i've to implement web security and i need the same relationship you are using. Anyway, i figured out that the problem wasn't in the entities.

我在同一个场景中遇到了同样的问题,因为我必须实现网络安全并且我需要你正在使用的相同关系。无论如何,我发现问题不在实体中。

You have to check (for my case) the insert and edit methods on the UserJPAController.java, those methods some how knows how the entities are referenced each other, so i implemented this code and it works fine.

您必须检查(就我而言)UserJPAController.java 上的插入和编辑方法,这些方法如何知道实体是如何相互引用的,所以我实现了这段代码并且它工作正常。

List<Grupo> attachedGrupoList = new ArrayList<Grupo>();
        for (Grupo grupoListGrupoToAttach : usuario.getGrupoList()) {
            grupoListGrupoToAttach = em.getReference(grupoListGrupoToAttach.getClass(),      grupoListGrupoToAttach.getIdGrupo());
            attachedGrupoList.add(grupoListGrupoToAttach);
        }
        usuario.setGrupoList(attachedGrupoList);
        em.persist(usuario);
for (Grupo grupoListGrupo : usuario.getGrupoList()) {
            grupoListGrupo.getUsuarioList().add(usuario);
            grupoListGrupo = em.merge(grupoListGrupo);
        }

After executing that code and the transaction has ended you will see the sql scripts executed by JPA in the Data Base.

执行该代码并且事务结束后,您将在数据库中看到由 JPA 执行的 sql 脚本。

Hope it helps!

希望能帮助到你!

Mike

麦克风