Hibernate Cascade:角色和员工

时间:2018-04-13 04:33:47

标签: spring hibernate spring-mvc hibernate-mapping hibernate-criteria

首先,我将简要介绍一下我的问题。

我正在开展一个试验项目来测试我最近在Hibernate中学到的东西。我们的想法是集成Spring,Spring MVC和Hibernate。似乎一切都运转得很好,直到我遇到这个问题,这花了我一整天但仍然没有解决方案。

这个想法非常简单。有两个实体,“角色”和“用户”。一个人可以拥有一个角色,这使得它成为多对一的关系。角色可以分配给很多人,这意味着一对多的关系。

因此,我的代码是这样的。角色:

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@Column(length=20,nullable=false,name="rolename",unique=true)
private String name;
@OneToMany(cascade=CascadeType.ALL, mappedBy="role")
private Set<UserBean> users = new HashSet<UserBean>();

用户:

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
@ManyToOne(optional=true,cascade=CascadeType.ALL,unique=true)
@JoinColumn(name="role_id")
    private RoleBean role=new RoleBean();

另外,我使用Spring MVC来绑定值。这是代码:

<form:form modelAttribute="user"
        action="${pageContext.request.contextPath}/add">
        <div>
            <form:input path="username" 
                 />
            <form:errors path="username" />
            <br>
            <form:password path="password" placeholder="password" />
            <form:errors path="password" />
            <br> <form:select path="role.name">
                <option value="clerk">clerk</option>
                <option value="salesperson">salesperson</option>
                <option value="manager">manager</option>
            </form:select>
        </div>
        <input type="submit" value="submit" />

    </form:form>

您会在前端页面看到我添加了<form:select>标记,希望此标记可以使用“级联”设置来完成工作。

它运作得很好。

然而,当我进一步测试代码时,发生了一些事情。

我的期望是理想情况下,Hibernate会收到“rolename”,然后使用名称创建一个角色项,并将这个新角色保存到数据库中。如果两个或多个用户使用相同的“rolename”(在此设置下是职员,经理或销售人员)注册,则hibernate可以理解,由于{{{},hibernate不应该再次将值插入“role”表中。 1}}设置。

然后发生了一些奇怪的事情。如果我使用相同的“rolename”向两个“用户”注册两次,hibernate会给我一个错误,上面写着:

unique=true

老实说,我知道这个错误是怎么发生的。这是因为Duplicate entry 'clerk' for key 'UK_a5k2ae0srn5n63xyhst1dllhq' 设置。但是,如果我删除此设置并重新运行编程,程序可能会自动将具有相同角色名称的多个“角色”项插入到系统中,以便表格看起来像这样:

"unique=true"

显然,这不是我想要的,因为没有人会期望公司/组织可以拥有完全相同角色名称的不同角色。

我认为在hibernate映射设置或级联中必定存在我做错的事情。但即使我努力在这里和通过谷歌搜索可能的答案,我还没有找到任何解决这个问题的方法。

那么,你介意给我一个可能的解决方案吗?

3 个答案:

答案 0 :(得分:0)

CascadeType.ALL的含义是持久性将所有EntityManager操作(PERSIST,REMOVE,REFRESH,MERGE,DETACH)传播(级联)到相关实体。

由于您不需要创建新的角色,因此您只需将其从角色中删除即可。

@OneToMany(mappedBy="role")
private Set<UserBean> users;

添加setter和getter。 。

用户相同。

答案 1 :(得分:0)

你应该改变一些事情:

  1. 在创建用户之前,角色应该存在。如果你想在创建用户时创建角色,那么你必须在你的后端手动处理它,而不是依赖于Hibernate。
  2. 角色一旦存在,您应该在渲染表单时将它们传递给前端。在表单中,您应该使用您在modelAttribute中添加的角色,如下所示(假设rolesList是包含所有可能角色的modelAttribute):
  3. <form:select path="role.id">
       <form:options items="${rolesList}" itemValue="id" itemLabel="name"/>
     </form:select>
    
    1. 通过这样做,后端将收到一个UserBean对象,RoleBean设置为前端的选定角色,Hibernate将负责保存role_id

答案 2 :(得分:0)

首先,我要感谢您回答我的问题并提出解决方案!

最后,我按照@Mubin的建议完成了这项工作。

我在控制器中添加了一些代码:

        ArrayList<RoleBean> rolelist = new ArrayList<RoleBean>();
        RoleBean r1 = new RoleBean();
        RoleBean r2 = new RoleBean();
        RoleBean r3 = new RoleBean();

        r1.setId(1);
        r1.setName("clerk");
        r2.setId(2);
        r2.setName("salesman");
        r3.setId(3);
        r3.setName("manager");
        rolelist.add(r1);
        rolelist.add(r2);
        rolelist.add(r3);

        view.addObject("rolelist", rolelist);

所以,简单地说,我将总结一下您的参考资料!

首先,我最初的想法是错误的。我以为我应该通过&#34;角色&#34;从前端到后端。但是,这个想法本身就是反逻辑的。公司创建角色,并将这些角色分配给不同的员工。员工很少需要公司为他们创建角色。

所以,首先,我应该首先使用SQL在数据库中创建角色。

在我弄清楚之后,一切都显得顺利。如果数据库中的角色保持不变,我需要做的就是将信息传递给用户表中的外键,将每个人与其角色相关联。

所以我使用了这个标签:

            <form:select path="role.id">
                <form:options items="${rolelist}" itemValue="id" itemLabel="name"/>         
            </form:select>

hibernate的作用是:

它从前端获取输入,检查&#34; itemValue&#34;,即user.role.id.然后比较这个值是否已经在数据库中(绝对是&#34;是&#34;),然后将id与用户角色链接。

我认为这非常重要,因为昨天,当我试图解决问题时,有一次尝试我只是删除了rolebean的cascade = ALL,然后程序引发了一个异常:瞬态实体未保存。

这是因为没有级联,程序只会保存&#34;用户&#34;没有保存&#34;角色&#34;第一。如果没有&#34;角色&#34;在表格中,没有&#34;角色ID&#34;附上。

所以,问题解决了!谢谢!