英文:
Spring Boot JPA how to handle child table updates
问题
我来自之前的工作背景,在那里我负责所有数据持久化工作,使用自定义的SQL和JDBC。我刚开始在一家小企业担任新工作,我是唯一的开发人员,并决定使用Spring Boot和JPA来开发业务系统。
我不知道在处理子表更新方面应该采取什么样的方法。目前我正在使用Spring Crud Repository处理基本表,但是遇到了第一个父子关系。
在下面的示例表结构中,我应该如何管理更新?
+-------------------------+
| Order |
+-------------------------+
| orderNumber | PK |
+-------------------------+
+-------------------------+
| OrderLine |
+-------------------------+
| orderNumber | PK |
+-------------------------+
| lineNumber | PK |
+-------------------------+
用户可能会更新或删除现有的订单行。
在进行更新时,我可以先删除所有现有的订单行,然后重新创建它们,但不确定这是否是不良实践?
在Spring Boot和JPA中,通常的方法是什么?
我应该在父实体上使用某种级联设置吗?
英文:
I've come from a background in my previous role of doing all data persistence with all custom SQL and JDBC. Just started a new job for a small business where I'm the only developer and have decided to develop the businesses systems using Spring Boot with JPA for data persistence.
I don't know how I should be handling updates on child tables. I'm currently using the Spring Crud Repository for basic tables but have got to my first parent child relationship.
Given the below example table structure, how should I be managing updates?
<pre>
+-------------------------+
| Order |
+-------------------------+
| orderNumber | PK |
+-------------------------+
+-------------------------+
| OrderLine |
+-------------------------+
| orderNumber | PK |
+-------------------------+
| lineNumber | PK |
+-------------------------+
</pre>
The users could update or delete existing order lines.
When doing an update, I could delete all of the existing orderLines first and recreate them but not sure if this is bad practice?
What is the normal approach with Spring Boot and JPA?
Should I be using some kind of cascade settings on the parent entity?
答案1
得分: 1
> 在执行更新操作时,我可以首先删除所有现有的orderLines,然后重新创建它们,但不确定这是否是一种不好的做法?
只更新需要更新的orderlines 是最佳实践。
> 我可以首先删除所有现有的orderLines,然后重新创建它们,
这将导致产生大量的删除查询和插入查询,这是不好的。orderlines的自动生成 id
也会迅速增加,这不是你想要的结果。
> 在Spring Boot和JPA中,通常的方法是什么?
父实体应该使用某种级联设置吗?
是的,你应该这样做。以下是一个示例:
Order.java
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderNumber;
@Version
private Long version = 0L;
@OneToMany(mappedBy="order", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<OrderLine> orderLines;
// equals() 和 hashcode() 实现
// getter() 和 setter() 实现
}
OrderLine.java
@Entity
public class OrderLine {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long lineNumber;
@ManyToOne
@JoinColumn(name="order_id", nullable=false)
private Order order;
@Version
private Long version = 0L;
// equals() 和 hashcode() 实现
// getter() 和 setter() 实现
}
最后是一个更新示例:
public boolean update(Order order, long orderLineId, OrderLine updatedOrderLine) {
if(order == null || updatedOrderLine == null)
return false;
if(order.getOrderLines() == null)
return false;
Optional<OrderLine> optTargetOrderLine = order.getOrderLines().stream()
.filter(orderline -> orderLine.getLineNumber() == orderLineId).findFirst();
if(!optTargetOrderLine.isPresent())
return false;
OrderLine targetOrderLine = optTargetOrderLine.get();
// 现在实现更新函数
boolean status = update(targetOrderLine, updatedOrderLine);
// 如果状态为true,还必须在OrderRepository上调用save()
return status;
}
以上为翻译内容,代码部分未翻译。
英文:
> When doing an update, I could delete all of the existing orderLines first and recreate them but not sure if this is bad practice?
updating only the orderlines that need an update is the best practice.
> I could delete all of the existing orderLines first and recreate them
That would cause to make a lot of delete queries and lot of insert queries which is bad. The autogenrated id
of orderlines would also increase rapidly which is not what you want.
> What is the normal approach with Spring Boot and JPA?
Should I be using some kind of cascade settings on the parent entity?
Yes, you should. Here is an example:
Order.java
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderNumber;
@Version
private Long version = 0L;
@OneToMany(mappedBy="order", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<OrderLine> orderLines;
// equals() and hashcode() implementation
// getter() and setter() implementation
}
OrderLine.java
@Entity
public class OrderLine {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long lineNumber;
@ManyToOne
@JoinColumn(name="order_id", nullable=false)
private Order order;
@Version
private Long version = 0L;
// equals() and hashcode() implementation
// getter() and setter() implementation
}
And finally an update example:
public boolean update(Order order, long orderLineId, OrderLine updatedOrderLine) {
if(order == null || updatedOrderLine == null)
return false;
if(order.getOrderLines() == null)
return false;
Optional<OrderLine> optTargetOrderLine = order.getOrderLines().stream()
.filter(orderline -> orderLine.getLineNumber() == orderLineId).findFirst();
if(!optTargetOrderLine.isPresent())
return false;
OrderLine targetOrderLine = optTargetOrderLine.get();
// now implement the update function
boolean status = update(targetOrderLine, updatedOrderLine);
// if status is true, you also have to call save() on your OrderRepository
return status;
}
答案2
得分: 0
Sure, here's the translation:
能否将orderNumber
替换为orderId
?orderLine
表通过外键orderId
引用Order
表,对于您的代码来说更有意义。如果可以的话,使用连接列和级联配置,而不是删除所有的orderLine
并重新创建它们,让JPA为您完成这些操作。
英文:
Could you replace orderNumber
with orderId
? The orderLine
table reference to the Order
table via foreign key orderId
has more meaning for your code. If you could, using join column and cascade config, instead of deleting all orderLine
and recreate them, let JPA do it for you.
答案3
得分: 0
你可以在Spring Data JPA中执行以下映射,以满足你上述的需求。你正在尝试的是Order
和OrderLine
之间的组合关系,前者是所有者,而不是父/子关系。
@Entity
@Table(name="Order")
class Order {
@Id
private Long orderNumber;
@OneToMany(mappedBy="order")
private List<OrderLine> orderLines;
}
@Entity
@Table(name="OrderLine")
class OrderLine {
@ManyToOne
@JoinColumn(name="orderNumber", nullable=false)
private Order order;
private Long lineNumber;
}
英文:
You can do the following mapping in Spring Data JPA for your entities to replicate the above requirement. What you are trying is a composition relationship between Order
and OrderLine
where former is the owner not a parent/child relationship.
@Entity
@Table(name="Order")
class Order {
@Id
private Long orderNumber;
@OneToMany(mappedBy="order")
private List<OrderLine> orderLines;
}
@Entity
@Table(name="OrderLine")
class OrderLine {
@ManyToOne
@JoinColumn(name="orderNumber", nullable=false)
private Order order;
private Long lineNumber;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论