【问题标题】:JPA many-to-many persist to join tableJPA多对多坚持加入表
【发布时间】:2013-10-28 05:48:04
【问题描述】:

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

没有错误信息只是持久化用户。

用户 用户组 组

我正在使用 netbeans 7.3、Glassfish 3.1.2.2、postgresql 9.1 和 eclipselink 2

另外,我尝试显示以下属性对我不起作用的 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"/>

抽象 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);
}
}

用户实体:

   @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

组实体:

@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

用户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;
    }
}

【问题讨论】:

    标签: java sql jpa eclipselink


    【解决方案1】:

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

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

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

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

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

    你必须检查(就我而言)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);
            }
    

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

    希望对你有帮助!

    迈克

    【讨论】:

      【解决方案2】:

      您需要启用cascade 进行合并(使用PERSIST)或使用ALL 进行所有操作。

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

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

      映射/连接表的工作方式是user_groupusergroup 表有一个外键 约束。这就是为什么必须在group 中插入一个新行,以便使用它的主键user_group 添加一个新行。

      这与 JPA 无关,即使您使用的是纯 JDBC,这同样适用于您。这就是 Entity-Relationships 在数据库中的工作方式。

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

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

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

      不过,启用此功能只是为了简化您的开发。这不应该用于通过指定此属性或将其值设置为 none 来禁用它的生产环境。

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

      【讨论】:

      • 如果我设置 CascadeType.PERSIST,它也会将数据插入到组表中。我要添加日期用户表和用户组表(pk_user,pk_group)
      • 这很不寻常。 user_group 将具有依赖于 group 表的外键约束。这就是为什么插入group,然后使用其主键向user_group 添加新行的原因。否则这是不可能的。
      • 'user_group' 具有带有 'group' 和 'user' 表的 fk。我还删除了所有表,它们是由 eclipse 链接自动生成的。它们是相同的,但不向 'user_group' 插入任何行
      • “user_group”表的外键为“users”和“groups”。当级联策略持续存在时,我了解 jpa 的行为。但我仍然无法处理这个。您可以在 git 上查看我的项目:github.com/erdoganonur/MkmTurizm.Thanks 寻求帮助。
      猜你喜欢
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-13
      • 2017-06-25
      相关资源
      最近更新 更多