Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java hibernate-合并父项仍在更新,而子项返回错误_Java_Hibernate_Spring Mvc_Hibernate Mapping - Fatal编程技术网

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