【问题标题】:Persist One to One relation Entity in Hibernate - Entity is detached在 Hibernate 中保持一对一关系实体 - 实体已分离
【发布时间】:2015-01-30 21:50:26
【问题描述】:

我有两个表是一对一的关系:

用户:

create table users (

  id int not null primary key,
  username varchar2(40) not null unique,
  password varchar2(60) not null,
  firstName varchar2(40) not null,
  lastName varchar2(40) not null,
  personalId varchar2(11) unique,
  city varchar2(40),
  address varchar2(40),
  email varchar2(40) not null unique,
  phone varchar2(9) unique
);

用户帐户

    create table usersAccounts (
  id int primary key,
  accountNr varchar2(26) not null unique,
  balance float not null,
  createDate date not null,
  expiredDate date,
  lastCharge date,
  userId int constraint userAccount_fk_user references users(id),
);

我的实体:

用户

    @Entity
@Table(name = "users")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "username")
    private String username;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 60)
    @Column(name = "password")
    private String password;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "firstName")
    private String firstName;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "lastName")
    private String lastName;
    @Size(min = 11, max = 11)
    @Column(name = "personalId")
    private String personalId;
    @Size(max = 40)
    @Column(name = "city")
    private String city;
    @Size(max = 40)
    @Column(name = "address")
    private String address;
    @NotBlank
    @NotNull
    @Email
    @Size(max = 40)
    @Column(name = "email")
    private String email;
    @Size(min = 9, max = 9)
    @Column(name = "phone")
    private String phone;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<UserRole> userRoleSet;
    @OneToOne(mappedBy = "user")
    private UserAccount userAccount;

用户帐户

    @Entity
@Table(name = "usersAccounts")
public class UserAccount implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotNull
    @Column(name = "accountNr")
    private String accountNr;
    @NotNull
    @Column(name = "balance")
    private float balance;
    @NotNull
    @Column(name = "createDate")
    private Date createDate;
    @Column(name = "expiredDate")
    private Date expiredDate;
    @Column(name = "lastCharge")
    private Date lastCharge;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "userId")
    private User user;

我尝试坚持这个,但我有错误:

    @RequestMapping(value = "/admin/addAdmin", method = RequestMethod.POST)
public String addAdmin(@ModelAttribute("user") UserDto userDto,
        BindingResult result) {
    AddUserValidator addUserValidator = new AddUserValidator();
    addUserValidator.validate(userDto, result);
    if (result.hasErrors()) {
        return "admin/addadmin";
    } else {
        ErrorMessage errorMessage;
        User user = prepareModelUser(userDto);
        if ((errorMessage = userService.createUser(user)) != null) {
            result.rejectValue(errorMessage.getPath(),
                    errorMessage.getDescription());
            return "admin/addadmin";
        } else {
            user = userService.findByUsername(user.getUsername());
            UserRole userRole = new UserRole("ROLE_ADMIN");
            userRole.setUser(user);
            userRoleService.createUserRole(userRole);
            UserAccount ua = new UserAccount();
            ua.setAccountNr("12345678901");
            ua.setBalance(100);
            DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            Date date = new Date();
            String dateStr = dateFormat.format(date);
            try {
                ua.setCreateDate(dateFormat.parse(dateStr));
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            user = userService.findUser(user.getId());
            ua.setUser(user);
            userAccountService.createUserAccount(ua);
            return "redirect:/admin/adminlist";
        }
    }
}

当我尝试坚持我得到这个错误:

严重:servlet [appServlet] 在路径 [/ibank] 的上下文中的 Servlet.service() 引发异常 [请求处理失败;嵌套异常是 javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: 分离的实体传递给坚持:pl.piotr.ibank.model.User] 根本原因 org.hibernate.PersistentObjectException:分离的实体传递给持久化:pl.piotr.ibank.model.User

userRole.setUser(user); userRoleService.createUserRole(userRole); 保存得很好,但是当我尝试ua.setUser(user); userAccountService.createUserAccount(ua); 时,我得到了分离的实体

【问题讨论】:

    标签: java hibernate jpa one-to-one


    【解决方案1】:

    同时让主键成为外键是非常糟糕的做法。尤其是当你有@GeneratedValue 时。

    仔细观察,您的实体映射正常,但 usersAccounts 表需要调整。从id 列中删除该外键约束,并添加新列userId,它将成为users#id 的外键。之后一切都应该正常工作。

    【讨论】:

    • 我编辑了我的第一篇文章。我利用了您的建议并在数据库中编辑了我的表格。但是当我尝试坚持时,我得到了新的错误。实体用户已分离。为什么? @Predrag Maric
    • 不看服务代码就很难判断。尝试简化您的代码,并保留与一个 UserAccount 相关的一个用户。成功后,添加代码的其他部分,看看是什么部分导致了问题。您应该为此编写一个单元测试,外部人员很难在此代码中导航。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    相关资源
    最近更新 更多