JpaRepository not saving entity
Solution 1
You should add @Transactional
annotation to your method, so spring will handle the transaction and commit your changes.
This usually comes on the @Service
class, but I see in your example that you do not have one, so put it on the controller (or add service layer, I think it's better)
Solution 2
You are ignoring dependency injection which is the beauty of spring framework.
- Make a Repository class which implements JPARepository and annotate it with @Repository.
- Make a Service class and annotate it with @Service and @Transactional.
- In Service class autowire the Repository and make corresponding methods call like .save() .find() etc.
- 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.
Related videos on Youtube
devil0150
Updated on October 02, 2022Comments
-
devil0150 over 1 year
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
-
devil0150 over 4 yearsI tried adding @Transactional, both to the class and to the method, both the one from javax.transaction, and the one from org.springframework.transaction.annotation. I still don't see the changes in the database after calling
changeEntity
-
devil0150 over 4 yearsDo I need to add something in application.properties?
-
Nir Levy over 4 yearstry setting the auto-commit property to true
-
devil0150 over 4 yearsI don't really know this property, but I did some googling and tried these: spring.datasource.auto-commit,spring.jpa.hibernate.autocommit, spring.jpa.hibernate.auto-commit, spring.jpa.properties.hibernate.autocommit, spring.jpa.properties.hibernate.auto-commit, hibernate.connection.autocommit, hibernate.connection.auto-commit. None worked
-
Raphael over 4 yearsRepositories are automatically implemented by Spring Data JPA, so you don't have to implement them yourself.
-
devil0150 over 4 yearsYou were right, just adding @Transactional was enough. I made some stupid mistakes while changing the code to test that and it didn't work at first.
-
Manish Bansal over 4 yearsYea, but to make more methods you need to make a interface and can add abstract method in it, rest its implementation will be given be spring.
-
judos over 2 yearsThere are different @Transactional annotations. Which one do you mean? Please add your import to show what is actually needed.