更新JPA实体

时间:2018-03-15 16:57:32

标签: spring spring-mvc jpa spring-data-jpa

我有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个字段的旧客户对象。?

3 个答案:

答案 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();
        }

请让我知道上述问题有哪些更好的解决方案。