2012-03-16 3 views
77

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

@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); 
    } 
} 
+0

схожих, может ссылаться http://stackoverflow.com/q/3328813/366964 –

+0

Спасибо за ответы. И как сложное решение (а не JPA), мы можем использовать другой уникальный идентификатор, такой как временная отметка unix. – sura2k

+1

Возможный дубликат [Когда JPA установлен @GeneratedValue @Id] (http://stackoverflow.com/questions/9087848/when-does-the-jpa-set-a-generatedvalue-id) – Raedwald

ответ

121

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

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

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

@Override 
public ABC addNewABC(ABC abc) { 
    abcDao.insertABC(abc); 
    return abc; 
} 
+6

Примечание: это необходимо для анонима поля id с '@ GeneratedValue' - все, что влечет за собой –

+0

Можете ли вы, пожалуйста, объяснить проблемы при попытке достичь этого с помощью составного id http://stackoverflow.com/questions/31362100/explain-behaviors-in-mapping-auto -incremented-composite-id-sequence-with-hiberna – bl3e

+0

Есть ли штраф за производительность (или любые другие отрицательные эффекты) ручной промывки после сохранения? –

-1
em.persist(abc); 
em.refresh(abc); 
return abc; 
+0

Этот метод не работал для меня. Получил эту ошибку: javax.persistence.PersistenceException: org.hibernate.HibernateException: этот экземпляр еще не существует как строка в базе данных] – rtcarlson

+0

@rtcarlson, да, это не сработает. если вы создаете новый объект, вам понадобится 'em.flush()' not 'em.refresh (abc)'. –

2

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

1

Это, как я это сделал:

EntityManager entityManager = getEntityManager(); 
EntityTransaction transaction = entityManager.getTransaction(); 
transaction.begin(); 
entityManager.persist(object); 
transaction.commit(); 
long id = object.getId(); 
entityManager.close(); 
+0

Его не работает, давая ноль в качестве возврата после сохранения данных в таблицу. либо обновление не работает в этом случае. Что я должен сделать для этого. пожалуйста, предложите способ ... Спасибо –

+0

@VikrantKashyap Пожалуйста, задайте новый вопрос с небольшим кодом и упомяните меня, чтобы я мог посмотреть. –

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

проверить, что @GeneratedValue обозначения есть в вашей организации class.This говорит JPA о вашей собственности объекта автоматически генерируемое поведении

Смежные вопросы