Почему идентификатор идентифицируется как нулевой в сущности после saveandflush, но не равен нулю в базе данных?

Я использую последнюю версию Spring Boot с Spring Data JPA и Hibernate. Используемая база данных - Oracle 11G. Я искал решение в течение нескольких дней, но ничего не помогло. Я изо всех сил пытаюсь получить идентификатор сущности, вновь вставленной (успешно) в базу данных. Я использую последовательность и триггер. например

Лицо:

    @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...

Триггер:

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;
/

Последовательность:

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

Запрос выполняется в контроллере. например

@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";
}

Результат после findAll {"id":81,"addressLine":"aa","addressLine2":"a","city":"a","postalCode":"a"}

но вот объект после System.out.println(сохранен);

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

Репозиторий:

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

Я подозреваю, что есть проблема с сеансом, данные просто еще не зафиксированы. Я прав? Как это решить? Спасибо!

2 ответа

Решение

Задача решена!

Перед получателем getId в объекте адреса была аннотация @Id.

Просто удалил аннотацию

До:

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

После:

public long getId() {
    return id;
}

У меня была похожая проблема. Я был в состоянии сохранить сущность в БД просто отлично, а значение идентификатора было в дБ. Но когда я получил объект через интерфейс REST, атрибут id был нулевым. Проблема в моем случае была вызвана побочным эффектом поддержки HATEOS в spring-data-rest, где id не возвращается в качестве атрибута, а вместо этого возвращается в качестве URL-адреса собственной ссылки HATEOS. Чтобы это исправить, в моем проекте должен был быть следующий класс:

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));
    }    
}
Другие вопросы по тегам