Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update entity from DTO with hibernate erases other fields

I have two classes, let say

@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
}

and the corresponding DTO

public class ProductDTO{
    private Long id;
    private String name;
    private ProviderDTO provider;
    //getter & setter
}

to simplify ProductDTO and product have the same attribute, I'm using dozer Mapping to map the entity to the DTO and send it to the view. I have a view where the user only can make changes in productDTO.name (it is an update) and when he sends the changes to the server I make something like

ProductServices.update(productDTO);

ProductServices has

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

inside productDao (I'm using spring so I'm injecting sessionFactory and doing, and ProductServices has the @Transactioanl annotation)

this.getCurrentSession().update(p);

So Hibernate make an update and sets provider_id=null, I know that it is right because the product that I'm sending to the ProductServices.update doesn't have provider set and Hibernate will take as the product doesn't have provider an update it in database. Problem is that I'm not sure how can I solve this, I'm newie with hibernate and the only solutions that I found is to perform a select and check field by field and see what value has changed, but if, for example, I have a more complex object I will have to write a lot of code to check every field.

Anybody knows a better solutions or how I can modify mi code to handle correctly this situation?

I'm using Spring 3.1 With hibernate 3.6.

Thanks in advance.

like image 206
UserMan Avatar asked Mar 19 '23 08:03

UserMan


1 Answers

The problem is not hibernate, the "problem" is Dozer.

You need to load the entity from the database first (Hibernate). Then let Dozer only modify the fields that you want to modify (but not the id), and then let Hibernate save the updated entity.

I don't know Dozer in detail, so that this code as an raw sketch:

@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);
}
like image 154
Ralph Avatar answered Apr 05 '23 20:04

Ralph