我有JPA实体客户说50个字段,我想使用html表单从最终用户更新。
我将实体的一个实例传递给html页面形式(使用百日咳),这个形式在50个中只有20个字段(包括ID字段)。现在提交表单后,我想将使用表单收到的数据中的20个字段更新到数据库。我没有得到上述问题的解决方案。一种解决方案是更新个别领域,但我认为这不是一个好的解决方案。
@Entity
public class Customer
{
...
50 fields
}
我的获取方法:
@GetMapping(value = "customer")
public String customer(Model model) {
Customer customer = null;
Optional<Customer> optional = customer Repo.findById(customerId);
if (optional.isPresent()) {
customer = optional.get();
}
model.addAttribute("customer", Customer);
return "customer";
}
Html表格:
<form action="updateCustomer">
----20 fields which I would like to get update from user are here
</form>
@PostMapping(value = "updateCustomer")
public String updateCustomer(Model model, @ModelAttribute Customer customer) {
if(customer==null) {
System.out.println("Customer object is null");
}
else
{
customerRepo.save(customer);
}
return "savedCustomer";
}
在post方法中,当我获得客户对象时,它只有20个字段数据而不是50个(客户实体具有总字段数),因为html表单只有20个字段需要更新。如何使用具有更新的20个字段的新客户对象更新具有50个字段的旧客户对象。?
答案 0 :(得分:0)
过去有三种方法可以解决这个问题
1)让页面获取有问题的Customer对象,使用该对象预填充表单,然后POST更改的客户对象。好处是更改客户的用户可以看到与客户相关的所有信息,并且您可以在后端轻松合并。缺点是额外的REST调用。
2)创建DTO,并将非空字段从DTO传输到实体。好处是您不必更新表单中的所有字段,也不需要额外的网络调用。缺点是它在后端是一种纯粹的痛苦。
3)创建DTO,并使其成为要保存的实体。好处是它很容易合并回数据库,没有什么可以阻止您将相同的表和字段映射到多个实体。缺点是您必须担心并发问题,这可能在您的工作流程中不起作用,并且DTO基本上是每个表单特定的。
答案 1 :(得分:0)
要对实体进行部分更新,您需要使用Criteria
API或JPQL
查询...这在JPA中称为投影,here is a quick example,
注意:如果您使用旧版本的JPA查询解析器(无JPQL
更新)+旧版本的JPA(当没有CriteriaUpdate
lib时),您可能无法使用此功能然后需要从客户端传递id从DB获取对象,从客户端更新20个属性并保存更改
答案 2 :(得分:0)
以下解决方案对我有用:
助手类:
公共类BeanCopy {
private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(
Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class, String.class, Date.class));
public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException
{
new BeanUtilsBean() {
@Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value != null && (primitiveTypes.contains(value.getClass()) )) {
super.copyProperty(dest, name, value);
}
}
}.copyProperties(dest, source);
}
}
这是我复制和强制更改数据库的方式:
try {
BeanCopy.nullAwareBeanCopy(DBcustomer,customer);
customerRepo.save(DBcustomer);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
请让我知道上述问题有哪些更好的解决方案。