gpt4 book ai didi

java - 外键更新异常: foreign keys set to null in Hibernate one-to-many relationship

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:46:39 24 4
gpt4 key购买 nike

我发现,当更新一对多关系中的父表时,子表上依赖数据的外键被设置为 null,从而在子表上留下孤立的记录。

我有两个用 Hibernate 标记注释的 Java 类。父表是:

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {

// Attributes.
@Id
@Column(name="PERSON_ID", unique=true, nullable=false)
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer personId;

@Column(name="NAME", nullable=false, length=50)
private String name;

@Column(name="ADDRESS", nullable=false, length=100)
private String address;

@Column(name="TELEPHONE", nullable=false, length=10)
private String telephone;

@Column(name="EMAIL", nullable=false, length=50)
private String email;

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="PERSON_ID")
private List<Book> books;

子表是:

Entity
@Table(name = "BOOK")
public class Book implements Serializable {

// Attributes.
@Id
@Column(name="BOOK_ID", unique=true, nullable=false)
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer bookId;

@Column(name="AUTHOR", nullable=false, length=50)
private String author;

@Column(name="TITLE", nullable=false, length=50)
private String title;

@Column(name="DESCRIPTION", nullable=false, length=500)
private String description;

@Column(name="ONLOAN", nullable=false, length=5)
private String onLoan;

// @ManyToOne
// private Person person;

但是当对一个人发布更新时,任何与父相关的书籍记录都设置为空。

Book 表是:

CREATE TABLE BOOK (
BOOK_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
AUTHOR VARCHAR(50) NOT NULL,
TITLE VARCHAR(100) NOT NULL,
DESCRIPTION VARCHAR(500) NOT NULL,
ONLOAN VARCHAR(5) NOT NULL,
PERSON_ID INTEGER,
CONSTRAINT PRIMARY_KEY_BOOK PRIMARY KEY(BOOK_ID),
CONSTRAINT FOREIGN_KEY_BOOK FOREIGN KEY(PERSON_ID) REFERENCES PERSON(PERSON_ID))

Person controller 中的update 方法是:

@RequestMapping(value = "/profile", method = RequestMethod.POST)
public String postProfile(@ModelAttribute("person") Person person,
BindingResult bindingResult,
Model model) {
logger.info(PersonController.class.getName() + ".postProfile() method called.");

personValidator.validate(person, bindingResult);
if (bindingResult.hasErrors()) {
return "view/profile";
}
else {
personService.update(person);
model.addAttribute("person", person);
return "view/options";
}
}

而实际的 DAO 级别的方法是:

@Override
public void update(Person person) {
logger.info(PersonDAOImpl.class.getName() + ".update() method called.");

Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
try {
transaction.begin();
session.update(person);
transaction.commit();
}
catch(RuntimeException e) {
Utils.printStackTrace(e);
transaction.rollback();
throw e;
}
finally {
session.close();
}
}

所以我假设 update 是问题的原因,但为什么呢?

我已经尝试过 mergepersistsaveOrUpdate 方法作为替代方法,但无济于事。

关于我的 Book 表没有 @ManyToOne 注释这一事实,禁用此标记是我可以让 LAZY 获取工作的唯一方法。

这个案例看起来也很像Hibernate one to many:"many" side record's foreign key is updated to null automaticallyHibernate Many to one updating foreign key to null , 但如果我将这些问题中指定的类更改应用到我自己的表中,我的应用程序甚至拒绝编译,因为在 Person 表中使用 mappedBy 出现问题。

欢迎提出任何建议。

Controller 方法更改为:

// Validates and updates changes made by a Person on profile.jap
@RequestMapping(value = "/profile", method = RequestMethod.POST)
public String postProfile(@ModelAttribute("person") Person person,
BindingResult bindingResult,
Model model) {
logger.info(PersonController.class.getName() + ".postProfile() method called.");

// Validate Person.
personValidator.validate(person, bindingResult);
if (bindingResult.hasErrors()) {
return "view/profile";
}
else {

// Get current Person.
Person currPerson = personService.get(person.getPersonId());

// Set Books to updated Person.
person.setBooks(currPerson.getBooks());
personService.update(person);

model.addAttribute("person", person);
return "view/options";
}
}

而且有效。

最佳答案

我假设 postProfile() 方法接收一个 Person 实例,该实例仅包含该人的 ID、姓名、地址等,由 Web 表单发布,但它的图书列表为 null 或为空。

并且您要告诉 Hibernate 去拯救那个人。所以你有效地告诉 Hibernate 这个由给定 ID 标识的人有一个新名字、一个新地址、一个新电子邮件......进入数据库。

因此,Hibernate 会按照您的指示进行操作:保存人的新状态。由于新人没有任何书籍,因此他之前拥有的所有书籍都变得无人所有。

您必须从数据库中获取实际的、持久的 Person 实体,并将实际应该修改的字段从新的 person 复制到持久的。

或者您必须从数据库中预加载持久性人物,并让 Spring 填充这个持久性人物,而不是每次都创建一个新实例。参见 http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/htmlsingle/#mvc-ann-modelattrib-methods .

关于java - 外键更新异常: foreign keys set to null in Hibernate one-to-many relationship,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24353347/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com