Update with field updatable = false



  • Use JPA + Spring Data + Hibernate to record. There's a service with this method. (JPA repository standard):

    @Transactional
    public EmployeeJpaBean create(final EmployeeJpaBean employeeJpaBean) {
        return employeeJpaRepository.saveAndFlush(employeeJpaBean);
    }
    

    The essence of EmployeeJpaBean has this field:

    @Column(name = "empl_name", unique = true, nullable = false, updatable = false)
    private String name;
    

    As you can see, it shouldn't be updatable. I'm checking it out at the test like this:

    @Test
    public void updateNameTest() {
        EmployeeJpaBean employeeJpaBean = new EmployeeJpaBean();
        employeeJpaBean.setName("old");
        EmployeeJpaBean saved = employeeService.create(employeeJpaBean); //1
        Long id = saved.getId();
    
    saved.setName("new name");
    saved = employeeService.create(employeeJpaBean); //2
    //падает Assert.assertEquals("old", saved.getName());
    EmployeeJpaBean read = employeeService.read(id); //3
    Assert.assertEquals("old", read.getName());
    

    }

    Assertion falls on the comment line. Looked what Hibernate wrote - when the code lines were marked 2 and 3 - the same select, but the output is different.

    1. In the first place, why do you have different results?
    2. and second, how do the wrong data not return from the saveAndFlush?



  • ♪ http://docs.oracle.com/javaee/6/api/javax/persistence/Column.html#updatable%28%29 ♪ updatable=false Only influences the generation of UPDATE requests.

    In line (1), we create a new essence and we must generate SQL INSERT Request. In line (2), we call method employeeJpaRepository.saveAndFlushwhich, http://docs.spring.io/autorepo/docs/spring-data-jpa/1.7.x/api/org/springframework/data/jpa/repository/JpaRepository.html#saveAndFlush-S- (sighs) https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java should cause save(entity) and flush()

    @Transactional
    public <S extends T> S saveAndFlush(S entity) {
        S result = save(entity);
        flush();
    
    return result;
    

    }

    In turn, method save(entity) has such a view:

    @Transactional
    public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
    

    }

    Since we already have an object, the method will be called. em.merge(entity);

    Let's go to the merge method description. Turning to http://download.oracle.com/otndocs/jcp/ejb-3_0-fr-oth-JSpec/ (sighs) http://download.oracle.com/otn-pub/jcp/ejb-3_0-fr-oth-JSpec/ejb-3_0-fr-spec-persistence.pdf?AuthParam=1501531629_a1278b338ffa49dd2766f4e4ccd669a6 On pdf, but it is possible to open a licensing agreement. Let's go to the section:

    3.2.4.1. Merging Detached Entity State
    The semantics of the merge operation applied to an entity X are as follows:

    • ♪ ♪ ♪

    • ♪ ♪ ♪

    • If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been anno- tated with the cascade element value cascade=MERGE or cascade=ALL annotation.


    A simpler version from the Internet:

    • if the entity is already in the persistence context (session), no action is taken, except for cascades

    Free translation:

    If X is managed, it will be ignored in merge surgery, but it will be applied to cascade-related objects. ♪ ♪

    But why do we still have SELECT in line (2)? And there's a request for "the most recent" version of our essence, to be followed by the mechanism. https://letslearnjava.quora.com/Dirty-Checking-in-Hibernate We've found changes and managed to generate UPDATE query.

    By summarizing the above and answering questions:

    1. Both results of SELECT requests are the same, but only merge returns the existing object from a session that has already changed the meaning name

    2. The approach may be proposed to modify the method in such a way

       @Transactional
      public EmployeeJpaBean create(final EmployeeJpaBean employeeJpaBean) {
      employeeJpaRepository.saveAndFlush(employeeJpaBean);

       return employeeService.read(employeeJpaBean.getId());
      

      }

    But I'll think about the second question. ♪ ♪




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2