2014-11-03 56 views
0

所以我有两个类之间的一对多和多对一的关系。当我尝试更新实体时,父级更新并且子级引发错误。在这种情况下,我期望父级更新回滚,但事实并非如此。由于我有一对多的关系,父对象的更新需要插入一个子对象,但是当子对象抛出一个错误时,父对象的更新不应该回滚?如果它有任何关系,则由于儿童/帐户实体的独特约束而导致孩子的错误被抛出。休眠 - 合并父母仍然得到更新,而孩子返回错误

下面是我的两个型号:

/** User model **/ 
@Entity 
@Table(name = "user") 
public class User { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "id", unique = true, nullable = false) 
private int id; 

@Column(name = "type") 
private String type; 

@Column(name = "username", nullable = false) 
private String username; 

... 

// define one to many relation between User and Account 

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
@JoinColumn(name = "user_id") 
private Set<Account> accounts; 

public User() { 
} 

@PrePersist 
void preInsert() throws ParseException { 
    ... 
} 

// field getters and setters 

... 

// returns Account list associated with User 
public Set<Account> getAccount() { 
    return accounts; 
} 

// set Account list associated with User 
public void setAccount(Set<Account> accounts) { 
    this.accounts = accounts; 
} 
} 

模型2:

/** Account model **/ 
@Entity 
@Table(name = "account", uniqueConstraints = 
@UniqueConstraint(columnNames = {"user_id", "entity_id", "branch_id", "type"})) 
public class Account { 
private int id; 

@Column(name = "user_id", nullable = false) 
private int user_id; 

... 

private User user; 

// constructor 
public Account() { 

} 

@PrePersist 
void preInsert() throws ParseException {  
    ... 
} 

// field getters and setters 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "id", nullable = false) 
public int getId() { 
    return id; 
} 
public void setId(int id) { 
    this.id = id; 
} 

... 

// define many to one relation between Account and User 

// get User associated with Account 

@ManyToOne 
@JoinColumn(name = "user_id", insertable = false, updatable = false) 
public User getUser() { 
    return user; 
} 

// set User associated with Account 
public void setUser(User user) { 
    this.user = user; 
} 
} 

的UserDAO:

@Repository("userDao") 
@Transactional(propagation = Propagation.REQUIRED) 
public class UserDAO { 
@PersistenceContext 
private EntityManager entityManager; 

public EntityManager getEntityManager() { 
    return entityManager; 
} 

public void setEntityManager(EntityManager entityManager) { 
    this.entityManager = entityManager; 
} 

public void insert(User user) { 
    entityManager.persist(user); 
} 

public void update(User user) { 
    entityManager.merge(user); 
} 
.... 
} 

用户服务(其中我打电话的更新)

@Service 
public class UserService { 
private UserDAO userDAO; 

public UserDAO getUserDao() { 
    return userDAO; 
} 

@Autowired 
public void setUserDao(UserDAO userDAO) { 
    this.userDAO = userDAO; 
} 

public boolean addUser(SignupComponent signupComponent) { 
    .... 
    else { 
     // case (4) 

     // get user object 
     User userObj = getUserDao().findUser(user.getPhone()); 

     // update user object, adding account and account details 
     Set<Account> accounts = userObj.getAccount(); 

     Account a = new Account(); 
     a.setBranch_id(signupComponent.branch_id); 
     a.setEntity_id(signupComponent.entity_id); 
     if (signupComponent.type != -1) { 
      a.setType(signupComponent.type); 
     } 
     a.setUser(userObj); 

     userObj.setAccount(accounts); 
     userObj.setEmail(signupComponent.user.getEmail()); 

     AccountDetails ad = new AccountDetails(); //never mind this line, i have another one to one relation with another entity 
     ad.setAccount(a); 

     a.setAccountDetails(ad); 

     accounts.add(a); 

     try { 
      getUserDao().update(userObj); 
      return true; 
     } 
     catch(Exception e) { 
      signupComponent.error = e.toString(); 
      return false; 
     } 
    } 
} 
} 
+0

试着把'@ Transactional'放在'UserService#addUser'方法上。 – sp00m 2014-11-03 14:29:22

回答

0

您正在定义两侧的JoinColumn。您需要在一侧定义。它如何在一行中存储任意数量的外键?相反,它必须让集合中的实体的表将外键返回到源实体表。

试试这个:

public class User{  

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy="user") 
private Set<Account> accounts; 

} 

User类

/** User model **/ 
@Entity 
@Table(name = "user") 
public class User { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "id", unique = true, nullable = false) 
private int id; 

@Column(name = "type") 
private String type; 

@Column(name = "username", nullable = false) 
private String username; 

... 

// FetchType should be Lazy to improve performance 

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user") 
private Set<Account> accounts; 
//mappedBy says that this side is inverse side of relation and source is user which is mapped by user field name in Account class 

public User() { 
} 

@PrePersist 
void preInsert() throws ParseException { 
    ... 
} 

// field getters and setters 

... 

// returns Account list associated with User 
public Set<Account> getAccount() { 
    return accounts; 
} 

// set Account list associated with User 
public void setAccount(Set<Account> accounts) { 
    this.accounts = accounts; 
} 
} 

Account类

/**账户模式**/

@Entity 
@Table(name = "account", uniqueConstraints = 
@UniqueConstraint(columnNames = {"user_id", "entity_id", "branch_id", "type"})) 
public class Account { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "id", nullable = false) 
private int id; 

@Column(name = "user_id", nullable = false) 
private int user_id; 

... 
@ManyToOne(cascade=CascadeType.ALL) 
@JoinColumn(name = "user_id", insertable = false, updatable = false) 
private User user; 

// constructor 
public Account() { 

} 

@PrePersist 
void preInsert() throws ParseException {  
    ... 
} 

// field getters and setters 

public int getId() { 
    return id; 
} 
public void setId(int id) { 
    this.id = id; 
} 

... 

// define many to one relation between Account and User 

// get User associated with Account 


public User getUser() { 
    return user; 
} 

// set User associated with Account 
public void setUser(User user) { 
    this.user = user; 
} 
} 

现在看到,当您保存用户时,账户类将不会更新,因为用户在反面。但是当您保存Account类时,账号表中的user_id将会更新,因为它是关系的源端。

+0

谢谢你的答案:)但是,这并不适用于我。 User_id是帐户表中的主键,我将用户中的id映射到帐户中的user_id,我的方式不正确?我尝试了你的建议,但是帐号插入的user_id的默认值不是用户的id。再次感谢您的帮助 – 2014-11-04 09:20:26

+0

在您的帐户类中,不需要指定private int user_Id – 2014-11-04 09:32:52

+0

以使事情更简单,我删除了多对一的映射,并保留了一对多的映射定义,如下所示:\t @OneToMany(fetch = FetchType。 EAGER,cascade = CascadeType.ALL) \t @JoinColumn(name =“user_id”) \t private Set accounts;尽管我仍然遇到同样的情况。奇怪的。 – 2014-11-04 09:59:56