title: Spring Boot JPA @Transactional @Service does not update, but @Transactional in controller does
body: <p>I have a very basic Spring Boot/JPA stack app, with a controller, service layer, and repository that does not persist updates as I understand it should.</p>
  
  <p>A trivial Entity:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Entity
  public class Customer {
  
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String name;
  
    protected Customer() {}
  
    public Customer(String name) { this.name = name; }
  
    // standard getters,setters //
  }
  </code></pre>
  
  <p>A trivial Repository:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Repository
  public interface CustomerRepository extends CrudRepository&lt;Customer, Long&gt; {}
  </code></pre>
  
  <p>A simple Service layer:</p>
  
  <pre class="lang-java prettyprint-override"><code>// If the service is @Transactional and the controller is not, the update does NOT occur
  @Transactional
  @Service
  public class CustomerService {
  
    private static final Logger LOG = getLogger(CustomerService.class);
  
    @Autowired
    private CustomerRepository customerRepository;
  
    boolean updateCustomerName(Long id, String name) {
      Customer customer = customerRepository.findOne(id);
  
      if (customer == null) { return false; }
  
      // Modifies the entity
      customer.setName(name);
  
      // No explicit save()
  
      return true;
    }
  }
  </code></pre>
  
  <p>And a REST controller that uses it all:</p>
  
  <pre class="lang-java prettyprint-override"><code>// If the controller is @Transactional and the service is not, the update occurs
  @RestController
  @RequestMapping("/mvc")
  public class CustomerController {
  
    @Autowired
    private CustomerService customerService;
  
    @RequestMapping(path = "{id}", method = RequestMethod.PUT)
    public ResponseEntity updateCustomerName(@PathVariable Long id, @RequestParam("name") String name) {
  
      customerService.updateCustomerName(id,name);
  
      return ResponseEntity.noContent().build();
    }
  }
  </code></pre>
  
  <p>These are wired together with a simple one-liner <code>SpringBootApplication</code> </p>
  
  <p>I have SQL debug logs enabled and see the selects, update, etc.</p>
  
  <p>With the code above: When the service method is invoked by the controller, the modified entity is <em>not</em> persisted.  SQL logs show the <code>select</code> of the entity but no <code>update</code>.</p>
  
  <p>There is also no update if nothing is marked <code>@Transactional</code></p>
  
  <p>However, simply by moving the <code>@Transactional</code> annotation from the service class to the controller class, the SQL <code>update</code> <em>does</em> occur.</p>
  
  <p>If I add an explicit <code>customerRepository.save(customer)</code> to the service method, the update also occurs.  But my understanding is that the ORM should automatically save modified persistent entities.</p>
  
  <p>I'm sure the issue has something to do with the EntityManager lifecycle in the web request, but I'm puzzled.  Do I need to do additional configuration?</p>
  
  <p>Complete example at <a href="https://github.com/monztech/SO-41515160" rel="nofollow noreferrer">https://github.com/monztech/SO-41515160</a></p>
  
  <p><strong>EDIT:</strong> This was solved, see below.  Per the Spring spec <code>@Transactional</code> does not work in package-private methods and mistakenly did not make the update service method public.</p>
  
  <p>The update will occur if the method is <code>public</code> and the service class has the <code>@Transactional</code> annotation.</p>
  
  <p>I do have another question, however.  Why is the <code>@Transactional</code> annotation necessary? (the update does not occur without it)  Shouldn't the entity manager still persist the object because of the open session in view mechanism that Spring uses, independent of any transaction?</p>