使用休眠模式从DTO更新实体会擦除其他字段

Use*_*Man 2 java spring hibernate jpa dto

我有两节课,可以说

@Entity
public class Product{
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    private Provider provider;
    //getter & setter
}

@Entity
public class Provider{
    @Id
    @GeneratedValue
    private Long id;
    private String name
    //getter & setter
}
Run Code Online (Sandbox Code Playgroud)

和相应的DTO

public class ProductDTO{
    private Long id;
    private String name;
    private ProviderDTO provider;
    //getter & setter
}
Run Code Online (Sandbox Code Playgroud)

为了简化ProductDTO和产品具有相同的属性,我使用推土机映射将实体映射到DTO并将其发送到视图。我有一个视图,用户只能在productDTO.name中进行更改(这是一个更新),当他将更改发送到服务器时,我会做出类似

ProductServices.update(productDTO);
Run Code Online (Sandbox Code Playgroud)

ProductServices有

@Transactional
public void update(ProductDTO p){
        Product p = DozerMapper.map(productDTO,ProductDTO.class);
        productDao.update(p);
}
Run Code Online (Sandbox Code Playgroud)

在productDao内部(我正在使用spring,所以我正在注入sessionFactory并执行此操作,并且ProductServices具有@Transactioanl批注)

this.getCurrentSession().update(p);
Run Code Online (Sandbox Code Playgroud)

因此,Hibernate进行了更新并设置了provider_id = null,我知道这是正确的,因为我要发送给ProductServices.update的产品没有设置提供者,而Hibernate将采用该产品没有提供者的更新它在数据库中。问题是我不确定如何解决此问题,我对hibernate感到陌生,而我发现的唯一解决方案是逐字段执行选择和检查,并查看值发生了变化,但是例如,我有一个更复杂的对象,我将不得不编写大量代码来检查每个字段。

有人知道更好的解决方案,或者我如何修改mi代码以正确处理这种情况?

我正在使用Spring 3.1和Hibernate 3.6。

提前致谢。

Ral*_*lph 5

问题不是冬眠的,“问题”是推土机。

您需要首先从数据库中加载实体(休眠)。然后,让Dozer仅修改要修改的字段(而不修改ID),然后让Hibernate保存更新的实体。

我不了解Dozer的详细信息,因此此代码是原始草图:

@Transactional
public void update(ProductDTO dto){
    Product p = productDao.loadById(dto.getId());
    DozerMapper.map(dto,p); //you need to configure dozer to that it only map the fields you want to map.
    productDao.update(p);
}
Run Code Online (Sandbox Code Playgroud)