hibernate - 当父级返回错误时,合并父级仍然会更新

时间:2014-11-03 13:59:36

标签: java hibernate spring-mvc hibernate-mapping

所以我在两个班级之间有一对多和多对一的关系。当我尝试更新实体时,更新父级并且子级抛出错误。在这种情况下,我希望回滚父更新,但事实并非如此。由于我有一对多的关系,父对象的更新应该插入一个子进程,但是当子进程发出错误时,父进程的更新是否应该回滚?如果它具有任何关系,则由于子/帐户实体的唯一约束而抛出了孩子的错误。

以下是我的两个模型:

/** 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;
        }
    }
}
}

1 个答案:

答案 0 :(得分:0)

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

试试这个:

public class User{    

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

}

用户类

/** 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; 
}
}

帐户类

/ **帐户模型** /

@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将会更新,因为它是关系的源端。