Search code examples
javahibernatejpacrudmodelmapper

Making JPA and ModelMapper work in entity updates


In my crud controller, the following is happening during Update operation

Client does a request to "POST /{id}" and sends me a DTO inside request body. Then I call ModelMapper to convert the DTO into a database entity. After that, I set the Id field of entity to the one client sent me. I do a repository save.

This fails (creates a brand-new entity instead of updating) since I'm trying to set an autogenerated field by hand. JPA EntityManager has a merge method, but I'm not sure if it does what I want.

So, I change my code to: first fetch the entity with the requested id, then ask ModelMapper to overwrite its fields, and finally do a repository save. However I couldn't make ModelMapper update an existing object instead of constructing a new instance. It looks possible according the docs, but I got lost between Providers and TypeMaps and whatnot.

So what I want is to either convince JPA to do an update with a transient entity, or to convince ModelMapper to set the fields of an existing (and jpa attached) entity.

The fact that a simple task got this convoluted makes me suspect I'm doing something fundamentally wrong. Can you suggest me a solution?


Solution

  • Are you looking for skip?

    public static void main(String[] args) {
        ModelMapper mapper = new ModelMapper();
        mapper.addMappings(new PropertyMap<B, A>() {
            @Override
            protected void configure() {
                skip(destination.getId());
            }
        });
        A a = new A(5, 15);
        B b = new B(7, 17);
        mapper.map(b, a);
        System.out.println(a.id); // prints 5
        System.out.println(a.x);  // prints 17
    }
    
    static class A {
        private int id;
        private long x;
    
        public A() {
        }
    
        public A(int id, long x) {
            this.id = id;
            this.x = x;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public long getX() {
            return x;
        }
    
        public void setX(long x) {
            this.x = x;
        }
    }
    
    static class B {
        // exact copy of A
    }