JpaRepository not saving entity

devil0150 picture devil0150 · Oct 12, 2019 · Viewed 11.9k times · Source

I have a server using spring boot and spring data jpa.

I have two classes annotated with @RestController in my server. One of them might change entities, while the other won't.

@RestController
@Slf4j
public class ControllerA {
    private EntityRepository entityRepository;

    public ControllerA(EntityRepository entityRepository) {
        this.entityRepository = entityRepository;
    }

    @PostMapping("/pathStr")
    public void changeEntity(@RequestParam("entityId") Long entityId) {
        // init
        Entity entity = entityRepository.findById(entityId);
        // make changes to entity
        entity.getOneToOneLinkedEntity().setIntProperty(0);
        // save entity
        entityRepository.save(entity);
    }
}

@RestController
@Slf4j
public class ControllerB {

    private Entity cachedEntity;
    private EntityRepository entityRepository;

    public ControllerB(EntityRepository entityRepository) {
        this.entityRepository = entityRepository;
    }

    @MessageMapping("/otherPath")
    public void getEntity(ArgumentType argument) {
        if (cachedEntity == null) {
            cachedEntity = entityRepository.save(new Entity());
        }
        Entity entity = entityRepository.findById(cachedEntity.getId()).orElse(null);
        int properyValue = entity.getOneToOneLinkedEntity().getIntProperty(); // this is not zero
    }
}

Here are the two entities and the repository:

@Entity
public class Entity implements Serializable {

    @Id
    @GeneratedValue private Long id;

    @NotNull
    @OneToOne(cascade=CascadeType.ALL)
    private OneToOneLinkedEntity linkedEntity;
}

@Entity
public class OneToOneLinkedEntity implements Serializable {

    @Id
    @GeneratedValue private Long id;

    @NotNull
    private int intProperty = 0;
}

public interface EntityRepository extends JpaRepository<Entity, Long> {
}

I make a call to ControllerA.changeEntity from the client, and once that returns, I make another call to ControllerB.getEntity. The changes I made in the first call aren't shown in the second call, (and they're not in the database either if I query directly with sql) the int property has an old value. Even though I do the save only on the Entity and not on the linkedEntity, the CascadeType.ALL should make the the linked entity update too, right?

I tried adding an entityRepository.flush() after the save in ControllerA, but the issue still appears. What can I do? How can I make ControllerB get the correct value of intProperty?

This is what I have in application.properties:

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/db_name
spring.datasource.username=user
spring.datasource.password=pass
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultComponentSafeNamingStrategy

Answer

Manish Bansal picture Manish Bansal · Oct 13, 2019

You are ignoring dependency injection which is the beauty of spring framework.

  1. Make a Repository class which implements JPARepository and annotate it with @Repository.
  2. Make a Service class and annotate it with @Service and @Transactional.
  3. In Service class autowire the Repository and make corresponding methods call like .save() .find() etc.
  4. In Controller Class autowire the service class and call service method which will call repository methods.

This is all you have to do. For making your application flow fast, better you create model for the entity class and pass the model between classes instead of entity as it contains a lot more information and thus much more heavy than normal model object.