JPA - Возврат автоматически сгенерированного идентификатора после сохранения()
Я использую JPA (EclipseLink) и Spring. Скажем, у меня есть простой объект с автогенерированным идентификатором:
@Entity
public class ABC implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
// ...
}
В моем классе DAO у меня есть метод insert, который вызывает 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);
}
}
Ответы
Ответ 1
Идентификатор гарантированно генерируется только во время очистки. Сохранение сущности только делает ее "прикрепленной" к контексту персистентности. Таким образом, либо очистите менеджера объектов явно:
em.persist(abc);
em.flush();
return abc.getId();
или вернуть сам объект, а не его идентификатор. Когда транзакция закончится, произойдет флеш, и пользователи сущности вне транзакции, таким образом, получат сгенерированный идентификатор в сущности.
@Override
public ABC addNewABC(ABC abc) {
abcDao.insertABC(abc);
return abc;
}
Ответ 2
@Entity
public class ABC implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
}
проверьте, что в классе сущности присутствует нотация @GeneratedValue. Это говорит JPA о вашем автогенерированном поведении объекта
Ответ 3
Вот как я это сделал:
EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();
Ответ 4
Вы также можете использовать GenerationType.TABLE вместо IDENTITY, который доступен только после вставки.
Ответ 5
Еще один вариант, совместимый с 4.0:
Перед CayenneDataObject
изменений вы можете восстановить новый объект CayenneDataObject
из коллекции, связанной с контекстом, например:
CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();
затем получите доступ к ObjectId
для каждого в коллекции, например:
ObjectId objectId = dataObject.getObjectId();
Наконец, вы можете выполнять итерацию по значениям, где обычно генерируемый идентификатор будет первым из значений (для ключа одного столбца) в карте, возвращаемой getIdSnapshot()
, он также содержит имена столбцов, связанных к ПК в качестве ключа (ей):
objectId.getIdSnapshot().values()
Ответ 6
Вот как я это сделал. Ты можешь попробовать
public class ABCService {
@Resource(name="ABCDao")
ABCDao abcDao;
public int addNewABC(ABC abc) {
ABC.setId(0);
return abcDao.insertABC(abc);
}
}
Ответ 7
em.persist(abc);
em.refresh(abc);
return abc;