当前位置: 首页 > 知识库问答 >
问题:

Hibernate saveorupdate或merge用于保存/更新一对多关系对象

逄岳
2023-03-14

我正在使用Spring MVC 3和Hibernate开发一个应用程序。我有两个类用户和租户详细信息与父子关系。在编辑详细信息功能中,我们可以编辑类用户的详细信息,动态添加classtenancedetails项并保存更改。我正在使用hibernate saveorupdate()方法来实现这一点,而hibernate正在为类用户创建一个新记录,这时它应该更新现有记录。这是我的密码。

模型类:

@Entity
@Table(name="tenancydetails")
public class TenancyDetails {

@Column(name="tenancyID")
@Id 
@GeneratedValue
private int tenancyId;  

@Column(name="landlordName")
@NotNull
private String landlordName;

@Column(name="landLordEmail") 
@NotNull
private String landlordEmail;

@Column(name="fromDate") 
@NotNull
private Date fromDate;

@Column(name="toDate")
@NotNull
private Date toDate;

@Column(name="location") 
@NotNull
private String location;

@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="userId", nullable=false)
private User user;

@Transient 
protected Object[] jdoDetachedState; 

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

public int getTenancyId() {
    return tenancyId;
}

public void setTenancyId(int tenancyId) {
    this.tenancyId = tenancyId;
}

public String getLandlordName() {
    return landlordName;
}

public void setLandlordName(String landlordName) {
    this.landlordName = landlordName;
}

public String getLandlordEmail() {
    return landlordEmail;
}

public void setLandlordEmail(String landlordEmail) {
    this.landlordEmail = landlordEmail;
}

public Date getFromDate() {
    return fromDate;
}

public void setFromDate(Date fromDate) {
    this.fromDate = fromDate;
}

public Date getToDate() {
    return toDate;
}

public void setToDate(Date toDate) {
    this.toDate = toDate;
}

public String getLocation() {
    return location;
}

public void setLocation(String location) {
    this.location = location;
}       
}

@Entity
@Table(name="User")
public class User {
@Column(name="userId")
@Id     
private int userId; 

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

@Column(name="emailId")
@NotEmpty(message = "Please enter your email id")
@Size(max = 50, message = "Email id can only be upto 50 characters long")
private String emailId;

@Column(name="password")
@NotEmpty(message = "Please enter your password")
@Size(max = 20, message = "Password can only be upto 20 characters long")
private String password;    

@OneToMany(cascade={CascadeType.ALL}, fetch = FetchType.EAGER)
@Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN,
    org.hibernate.annotations.CascadeType.PERSIST,
    org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinColumn(name="userId"/*, nullable=true*/)
@LazyCollection(LazyCollectionOption.FALSE)
private List<TenancyDetails> tenancyDetails = null;

public User(){
    tenancyDetails = new AutoPopulatingList<TenancyDetails>(TenancyDetails.class);
}

public List<TenancyDetails> getTenancyDetails() {
    return tenancyDetails;
}

public void addTenancyDetail(TenancyDetails tenancyDetail) {
    if (!tenancyDetails.contains(tenancyDetail)) {
        tenancyDetails.add(tenancyDetail);
    }
}

public void setTenancyDetails(List<TenancyDetails> tenancyDetails) {
    this.tenancyDetails = tenancyDetails;
}

public int getUserId() {
    return userId;
}

public void setUserId(int userId) {
    this.userId = userId;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getEmailId() {
    return emailId;
}

public void setEmailId(String emailId) {
    this.emailId = emailId;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}   

}

控制器:

@RequestMapping(value = "/Profile/{userId}",  method = RequestMethod.POST)
    public ModelAndView saveProfileDetails(@PathVariable int userId, Model model, HttpServletRequest request, HttpServletResponse response,
            HttpSession session, ModelMap modelMap, @ModelAttribute("user") User user) {            
        System.out.println("am in save");
        model.addAttribute("user", user);
        System.out.println(user.getPassword());
        System.out.println(user.getTenancyDetails().get(0).getUser().getUserId());
        System.out.println(model.containsAttribute("user"));        
        tenantRatingService.saveProfileDetails(user);
        return new ModelAndView("editProfile","user", user);
    }

DAO方法:

public void saveProfileDetails(User user){      
        System.out.println("inside the save profile method");
        Session session = getSession();
        Transaction transaction = session.beginTransaction();
        System.out.println("before save: " + user.getPassword());
        System.out.println("before save: " + user.getTenancyDetails().get(0).getUser().getUserId());        
        session.saveOrUpdate(user);
        transaction.commit();
        session.flush();
        System.out.println(user.getPassword());
    }

我还将这两个类的id字段设置为mysql中的AUTO_INCREMENT字段。我使用的一对多映射或@GeneratedValue有问题吗?还是与saveorupdate()方法有关?在这种情况下我应该使用merge()吗?就在saveorupdate()语句之前,已正确打印出现有用户ID的值!

有人能告诉我哪里出了问题吗?提前谢谢。

共有1个答案

闻人嘉颖
2023-03-14

我不知道,在呈现表单时,你是如何将用户对象放入你的模型中的,这最终涉及到你的POST方法:“/Profile/{userId}”。用户对象的id变为0。这就是为什么saveOrUpdate方法再次保存您的用户。要验证它,您可以在进入saveProfileDetails方法之前添加以下行:

user.setUserId(userId);

你的问题就会解决。

您还可以通过在"/Profile/{userId}"GETPOST方法的拥有控制器之前放置@SessionAtorites("user")来解决此问题。

另请参见:

  • 使用@会话属性存储模型属性
 类似资料:
  • 问题内容: 我有2个班级:驾驶员和汽车。汽车表在单独的过程中更新。我需要的是在Driver中具有属性,该属性使我可以阅读完整的汽车说明,并仅写入指向现有Car的ID。这是示例: 汽车对象只是典型的JPA对象,没有向后引用驱动程序。 因此,我想通过以下方法实现的目标是:1)我可以使用详细的JSON View阅读完整的汽车描述2)或在简短的JsonView 3中仅阅读汽车的ID 3),最重要的是,在创

  • 问题内容: 也许这是一个愚蠢的问题,但这困扰了我。 我有一个从员工到车辆的双向一对多关系。当我第一次将Employee保留在数据库中时(即它没有分配的ID),我也希望保留其关联的Vehicles。 目前,这对我来说很好,除了我保存的Vehicle实体没有自动映射关联的Employee,并且在数据库中Vehicle表中的employee_id外键列为空。 我的问题是,是否可以在雇员本身被保留的同时保

  • 问题内容: 我在个人课程和汽车课程之间有一对多的关系。一个人可以拥有许多汽车,反之亦然。我正在使用Restful API发布数据。我的注释和Get服务运行正常,但是我的后服务在每次尝试插入新数据时都抛出“ 。子表插入为” 。 这是我的代码的一部分。 人.java 汽车.java 我的服务等级: 问题答案: 此注释: 有两个后果: 暗示这是关系的拥有方。这意味着,每当要在和之间建立关系时, 都需要通

  • Car对象只是典型的JPA对象,没有对驱动程序的反向引用。 所以我试图通过这个来实现的是: 我可以使用详细的JSON视图阅读完整的汽车说明 或者我可以只读取汽车的Id,简写为jsonview 最重要的是,在创建新的驱动程序时,我只想传入汽车的JSON ID。这样,我就不需要在persist期间对Car进行不确定的读取,而只需要更新ID。 谢谢你。 更新:忘记了,我在创建驱动程序时通过的汽车的ID是

  • 我正在尝试使用Laravel保存方法保存关系: var_转储请求- 我已经在模型上尝试过填充和保护,但没有任何效果。但是,save方法不需要这些,因为它使用了一个完整的雄辩的模型实例。 我在这里错过了什么??