JPA - возврат автоматически сгенерированного идентификатора после persist () - PullRequest
95 голосов
/ 16 марта 2012

Я использую JPA (EclipseLink) и Spring.Скажем, у меня есть простая сущность с автоматически сгенерированным идентификатором:

@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;

     // ...
}

В моем классе DAO у меня есть метод вставки, который вызывает persist() для этой сущности.Я хочу, чтобы метод возвращал сгенерированный идентификатор для новой сущности, но когда я проверяю его, он возвращает 0.

public class ABCDao {
    @PersistenceContext
    EntityManager em;

    @Transactional(readOnly=false)
    public int insertABC(ABC abc) {
         em.persist(abc);
         // I WANT TO RETURN THE AUTO-GENERATED ID OF abc
         // HOW CAN I DO IT?
         return abc.id; // ???
    }
}

У меня также есть класс обслуживания, который переносит DAO, если это делаетразница:

public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         return abcDao.insertABC(abc);
    }
}

Ответы [ 7 ]

156 голосов
/ 16 марта 2012

Идентификатор гарантированно генерируется только во время сброса. Сохранение сущности только делает ее «привязанной» к контексту постоянства. Итак, либо очистите менеджер сущностей явно:

em.persist(abc);
em.flush();
return abc.getId();

или вернуть сам объект, а не его идентификатор. Когда транзакция заканчивается, происходит сброс, и пользователи сущности за пределами транзакции, таким образом, увидят сгенерированный идентификатор в сущности.

@Override
public ABC addNewABC(ABC abc) {
    abcDao.insertABC(abc);
    return abc;
}
11 голосов
/ 11 апреля 2016
@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;   
}

проверьте, присутствует ли нотация @GeneratedValue в вашем классе сущности. Это сообщает JPA об автоматически генерируемом поведении свойства сущности

3 голосов
/ 11 августа 2015

Вот как я это сделал:

EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();
2 голосов
/ 19 марта 2012

Вы также можете использовать GenerationType.TABLE вместо IDENTITY, который доступен только после вставки.

0 голосов
/ 27 мая 2019

Вот как я это сделал. Вы можете попробовать

    public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         ABC.setId(0);
         return abcDao.insertABC(abc);
    }
}
0 голосов
/ 28 августа 2018

Другая опция, совместимая с 4.0:

Перед фиксацией изменений вы можете восстановить новые объекты CayenneDataObject из коллекции, связанной с контекстом, например:

CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();

затем получите доступ к ObjectId для каждого в коллекции, например:

ObjectId objectId = dataObject.getObjectId();

Наконец, вы можете выполнять итерации по значениям, где обычно генерируемый идентификатор будет первым из значений(для ключа одного столбца) на карте, возвращаемой getIdSnapshot(), он также содержит имена столбцов, связанных с PK в качестве ключа (ключей):

objectId.getIdSnapshot().values()
0 голосов
/ 18 марта 2012
em.persist(abc);
em.refresh(abc);
return abc;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...