jordan.baucke
jordan.baucke

Reputation: 4328

Spring-Data Calling Save on Entity from Controller

I am using Spring Data within Spring Boot. I have a simple controller method that accepts an instance of an entity I'd like to update in my database. However, after calling repository.save() the object isn't persisted, however, if I query for the object (from the Id of the incoming entity) I have no problem, and the update persists.

Also the HTTP response is a 405 that the method doesn't work?

Controller:

@Transactional
public class AccountController {
    @Autowired
    private AccountService accountService;

    @RequestMapping(value = "/account/{id}", method = RequestMethod.PUT)
    @ResponseStatus(value = HttpStatus.OK)
    public @ResponseBody Account updateAccount(@PathVariable("id") String id, @RequestBody Account account) {
        return accountService.updateAndValidateAccountProfile(account);
    }
}

Service:

@Override
public Account updateAndValidateAccountProfile(Account account) {
    // calling findOne() returns the object ... and the save() works fine
    //Account currentAccount = accountRepository.findOne(account.getId());
    return accountRepository.save(account);
}

Repository:

interface AccountRepository extends CrudRepository<Account, Long> {

}

Is there something about the way I need to identify the object to Spring Data. I see the select statements fire out of hibernate, and I know the merge should happened on the primary key (id) within the Spring Data call to .save() - so I shouldn't need to query the object and manually assign the updated values correct??

Upvotes: 2

Views: 7086

Answers (1)

gadget
gadget

Reputation: 1978

Have you enabled transaction management? You need to use @EnableTransactionManagement on your config class otherwise @Transactional has no effect.

A spring tutorial on Managing Transactions

As a side note: making the controller layer transactional is usually not a good idea, especially when you have a proper separation of controller, service and repository layers. Consider moving @Transactional into the service layer.

Since you are using JPA, also make sure you have a JpaTransactionManager configured:

@Bean
public PlatformTransactionManager transactionManager() {
    return new JpaTransactionManager();
}

You might try extending the JpaRepository interface instead of CrudRepository then you can use saveAndFlush(entity) to make sure the changes are immediately flushed after merge.

Upvotes: 4

Related Questions