3

I use the latest Spring Boot with Spring Data JPA and Hibernate. The database used is Oracle 11G. I've been searching a solution for a couple of days but nothing worked. I struggle to retrieve the id of an entity newly inserted (successfully) in the database. I use a sequence and a trigger. e.g.

The entity:

    @Entity
    public class Address implements Serializable {
    @Id
    @Column(name = "ID", nullable = false, precision = 0)
    @SequenceGenerator(name = "SEQ_ID_GEN", sequenceName = "GI2S1.SEQ_ID", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID_GEN")
    private long id;
    private String addressLine;
    private String addressLine2;
    private String city;
    private String postalCode;

    @Id
    public long getId() {
        return id;
    }
    Getters & setters omitted...

The trigger:

CREATE OR REPLACE TRIGGER SEQ_ADDRESS_TRIG
    BEFORE INSERT ON ADDRESS
    FOR EACH ROW
BEGIN
    SELECT SEQ_ID.nextval
    INTO :new.id
    FROM dual;
END;
/

The sequence:

CREATE SEQUENCE SEQ_ID START WITH 1 INCREMENT BY 1 MINVALUE 1;

The query is performed in the controller. e.g.

@Controller
@RequestMapping("/address")
public class AddressController {

@Autowired
private AddressRepository addressRepository;

@Transactional
public Address saveAddress(Address address) {
    try {
        return addressRepository.saveAndFlush(address);
    } catch (Exception ex) {
        System.out.println(ex);
    }
    return null;
}

@PostMapping("/create")
public String create(@ModelAttribute Address address) {
    Address saved = saveAddress(address);
    long id = saved.getId();

    System.out.println(saved);

    return (id > 0) ?
            "redirect:/address/find?id=" + id
            :
            "redirect:/address/list";
}

The result after a findAll {"id":81,"addressLine":"aa","addressLine2":"a","city":"a","postalCode":"a"}

but here is the object after a System.out.println(saved);

Address{id=0, addressLine='aa', addressLine2='a', city='a',
postalCode='a'}

The repository:

@Transactional
public interface AddressRepository extends JpaRepository<Address, Long> {
    List<Address> findByCity(String city);
}

I suspect there's a problem with the session, the data isn't just yet committed. Am I right? How to resolve it? Thanks!

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Ivan
  • 129
  • 3
  • 6

2 Answers2

1

Problem solved!

There was an @Id annotation before the getter getId in the address entity.

Just removed the annotation

Before:

@Id
public long getId() {
    return id;
}

After:

public long getId() {
    return id;
}
Ivan
  • 129
  • 3
  • 6
  • 2
    Why did this fix the problem? – Glenn Bech May 09 '17 at 07:15
  • 1
    Hibernate probably detected that annotation and gave it precedence over the other one. This leads to hibernate only considering annotations on getters and setters. So the annotations specifying the use of the sequence get ignored. – Jens Schauder Apr 23 '18 at 04:37
0

I had a similar problem. I was able to persist entity to db just fine and id value was in db. But when I retrieved the entity via REST interface the id attribute was null. The problkem in my case was due to a side effect of HATEOS support in spring-data-rest where id is not returned as an attribute but instead is returned as a HATEOS self link url. To fix this I had to have the following class in my project:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;

import javax.persistence.EntityManager;
import javax.persistence.metamodel.Type;

@Configuration
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
    @Autowired
    private EntityManager entityManager;

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(
                entityManager.getMetamodel().getEntities().stream()
                        .map(Type::getJavaType)
                        .toArray(Class[]::new));
    }    
}
Farrukh Najmi
  • 5,055
  • 3
  • 35
  • 54