Java hibernate-合并父项仍在更新,而子项返回错误
所以我在两个类之间有一对多和多对一的关系。当我尝试更新一个实体时,父实体被更新,子实体抛出一个错误。在这种情况下,我希望父更新能够回滚,但事实并非如此。因为我有一对多的关系,父对象的更新需要插入子对象,但是当子对象抛出错误时,父对象的更新不应该回滚吗?如果是任何关系,则由于子/帐户实体上的唯一约束而引发子错误 以下是我的两个模型:Java hibernate-合并父项仍在更新,而子项返回错误,java,hibernate,spring-mvc,hibernate-mapping,Java,Hibernate,Spring Mvc,Hibernate Mapping,所以我在两个类之间有一对多和多对一的关系。当我尝试更新一个实体时,父实体被更新,子实体抛出一个错误。在这种情况下,我希望父更新能够回滚,但事实并非如此。因为我有一对多的关系,父对象的更新需要插入子对象,但是当子对象抛出错误时,父对象的更新不应该回滚吗?如果是任何关系,则由于子/帐户实体上的唯一约束而引发子错误 以下是我的两个模型: /** User model **/ @Entity @Table(name = "user") public class User { @Id @Generated
/** 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;
}
}
用户道:
@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);
}
....
}
用户服务(我在其中调用更新)
@服务
公共类用户服务{
私有UserDAO UserDAO;
公共UserDAO getUserDao(){
返回userDAO;
}
@自动连线
公共void setUserDao(UserDAO UserDAO){
this.userDAO=userDAO;
}
公共布尔addUser(SignupComponent SignupComponent){
....
否则{
//案例(4)
//获取用户对象
User userObj=getUserDao().findUser(User.getPhone());
//更新用户对象,添加帐户和帐户详细信息
Set accounts=userObj.getAccount();
账户a=新账户();
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(账户);
userObj.setEmail(signupComponent.user.getEmail());
AccountDetails ad=new AccountDetails();//不用管这行,我与另一个实体有另一个一对一的关系
ad.setAccount(a);
a、 设置帐户详细信息(ad);
增加(a);
试一试{
getUserDao().update(userObj);
返回true;
}
捕获(例外e){
signupComponent.error=e.toString();
返回false;
}
}
}
}
您正在两侧定义JoinColumn。您需要在一侧定义。它如何在一行中存储任意数量的外键?相反,它必须让集合中实体的表具有返回到源实体表的外键
试试这个:
public class User{
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy="user")
private Set<Account> accounts;
}
现在请看,当您保存用户时,帐户类将不会更新,因为用户位于反向端。但当您保存Account类时,Account表中的用户id将得到更新,因为它是关系的源端。尝试将
@Transactional
放在UserService#addUser
方法上。谢谢您的回答:)但是这对我不起作用。User\u id是account表中的主键,我将User中的id映射到account中的User\u id,我的方式不正确?我尝试了你的建议,但随后帐户被插入,用户id为默认值,而不是用户id。再次感谢您在account类中提供的帮助,无需指定private int user_id为简化操作,我删除了多对一映射,并保留了定义如下的一对多映射:@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)@JoinColumn(name=“user_id”)private Set accounts;不过我还是有同样的情况。奇怪,你做的事情真奇怪@不应在列表中定义JoinColumn,因为它不能有很多外键。实际上,这是一个映射错误!非常感谢。我确实从Account表中删除了user\u id属性,并将其映射为:@ManyToOne@JoinColumn(name=“user\u id”)和@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy=“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;
}
}
}
}
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;
}
}