gpt4 book ai didi

java - Hibernate 在更新父对象时不更新子对象

转载 作者:行者123 更新时间:2023-12-01 14:24:04 25 4
gpt4 key购买 nike

我有两个表,父表和子表之间有@oneTomany 关系。以下是我的表结构。

表结构

CREATE TABLE `parent` (
`id_parent` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id_parent`)
)

CREATE TABLE `child` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`parent_id` int(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_parent_child` (`group_id`),
CONSTRAINT `fk_parent_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id_parent`)
)

我已经为此创建了实体类,如下所示

父类。

@Entity
@Table(name = "parent")
public class Parent {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_parent")
private int id;

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

@OneToMany(mappedBy = "defaultchild", fetch = FetchType.EAGER)
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE })
private Set<Child> childs;

//setter and getters.
}

子类。

@Entity
@Table (name = "child")
public class Report {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column (name = "id")
private int id;
@Column (name = "name")
private String name;

@ManyToOne
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.MERGE})
@JoinColumn(name="parent_id")
private Parent defaultchild;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "group",joinColumns={@JoinColumn(name="fk_child_id")},inverseJoinColumns={@JoinColumn(name="fk_group_id")})
private Set<XXX> groups = new HashSet<XXX>(0);
//Setter and Getter methods
}

服务等级

public UIGroup getParentByName(String name) {
return DAO.getParentByName(name);
}

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public boolean updateParent(Parent parent) {
return DAO.updateParent(parent);
}


@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public boolean deleteParent(Parent parent) {
return DAO.deleteParent(parent);
}

DAO 类。

public UIGroup getParentByName(String name) {
Query query;
Parent parent = null;
try {
String queryString = " from Parent where name = :name";
query = sessionFactory.getCurrentSession().createQuery(queryString);
query.setParameter("name", name);
uiGroup = (Parent) query.uniqueResult();
} catch (Exception e) {
logger.error(e);
}
return parent;
}

public boolean updateParent(Parent parent) {
boolean result = true;
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
session.merge(parent);
tx.commit();
session.flush();
} catch (HibernateException e) {
result = false;
logger.error(e);
}// end of try-catch block.
return result;
}


public boolean deleteParent(Parent parent) {
boolean result = true;
Session session = null;
try {
session = sessionFactory.getCurrentSession();
session.delete(parent);
} catch (HibernateException e) {
result = false;
logger.error( + e);
}
return result;
}

但是当我试图调用下面的代码时

Parent otherParent = Service.getParentByName("Other");
Parent parent = Service.getParentByName("XYZ");
//here I am assigning childs assign to XYX parent to other Parent
Set<Child> childs = new TreeSet<Child>(Child.COMPARE_BY_ID);
childs.addAll(otherParent.getchildes());
childs.addAll(parent.getchilde());
otherParent.setChilds(childs);
Service.updateParent(otherParent);
Service.deleteParent(parent);

我遇到以下错误。

错误

java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`database`.`child`, CONSTRAINT `fk_parent_child` FOREIGN KEY (`parent_id`) REFERENCES `child` (`id_parent`))

这意味着我的更新代码无法正常工作以下是 Service.updateParent(otherParent) 语句的日志

SELECT parent0_.id_parent AS id1_135_1_, parent0_.name AS name135_1_, childs1_.parent_id AS parent4_3_, childs1_.id AS id3_, childs1_.id AS id143_0_, childs1_.child_name AS child2_143_0_, childs1_.is_sea_child AS is3_143_0_, childs1_.parent_id AS parent4_143_0_ 
FROM ui_parent parent0_
LEFT OUTER JOIN child childs1_ ON parent0_.id_ui_parent=childs1_.parent_id
WHERE parent0_.id_parent=1

请帮帮我,我不知道这段代码出了什么问题提前致谢。

最佳答案

我可能只编写一个 DAO 方法 moveAllChildren(String srcName, String dstName),如下所示:

public class ParentDAO {
@PersistenceContext
private EntityManager em;

public Parent findParentByName(name) {
TypedQuery<Parent> q = em.createQuery("select p from Parent where p.name = :name", Parent.class);
return q.setParameter("name", name).getSingleResult();
}

public void moveAllChildren(String srcName, String dstName) {
Parent src = findParentByName(srcName);
Parent dst = findParentByName(dstName);
Set<Child> children = new HashSet<Child>();
for (Child c: src.getChildren()) {
children.add(c);
}
src.getChildren().removeAll(children);
dst.getChildren().addAll(children);
}
}

一般来说,在使用级联时,最好的做法是显式地添加和删除子项,而不是说 dst.setChildren(allChildren),以便让 JPA 有机会管理关系的两边。如果您不这样做,您就有可能让 child 仍然认为 src 是他们的 parent ,然后您可能会从您的数据库中看到约束冲突。

此外,尝试让 JPA 管理尽可能多的实体内容是一个好主意。所以我宁愿不让应用程序调用服务调用 DAO 来检索 parent 只是为了移动他们的 child ,然后调用相同的服务调用相同的 DAO 将这些更改合并到数据库中。您最好将其实现为 DAO 级别的低级操作,然后添加调用它来处理 @Transaction 的服务。

关于java - Hibernate 在更新父对象时不更新子对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15271567/

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