2011-02-02 1 views
7

Я использую JPA TOPLINK заменимых и SQL Server 2008Почему JPA persist() не генерирует первичный идентификатор автоинкремента?

Моя цель состоит в том, чтобы получить автоматическое приращение значение первичного ключа данных, который будет вставлен в таблицу. Я знаю, что в JDBC есть метод getInsertedId(), который дает вам идентификатор первичного идентификатора автоматического инкремента (но это происходит после выполнения инструкции insert).

В JPA я узнал, что @GenratedValue annotation может сделать трюк.

@Entity 
@Table(name = "tableOne") 
public class TableOne implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "tableId") 
    private Integer tableId; 

Теперь, если я запускаю этот код он должен дать мне авто увеличивается идентификатор но он возвращает NULL ...

EntityManager em = EmProvider.getInstance().getEntityManagerFactory().createEntityManager(); 
EntityTransaction txn = em.getTransaction(); 
txn.begin(); 

TableOne parent = new TableOne(); 
em.persist(parent); //here I assume that id is pre-generated for me. 
System.out.println(parent.getTableId()); //this returns NULL :(
+0

Я могу получить полученный id, если я совершу: em.getTransaction(). Commit(), но нет способа получить идентификатор уже с persist ??? hmm –

+0

Ваш код должен работать так, как вы ожидаете. Я протестировал его, и я получу идентификатор, прежде чем совершить, или если я откажусь. Странно, что это не так. – Joel

+0

Не имеет значения, если tableId является int, а не Integer? – Joel

ответ

2

Мы также используем SQL Server 2008 и его никогда не работал для меня, поэтому я всегда выполняю отдельный запрос "SELECT @@IDENTY", чтобы получить вставленный идентификатор.

Причина, по которой я нашел в сети, заключалась в том, что автоматический идентификатор (IDENTITY) управляется базой данных и никогда не выбирается в Entity до тех пор, пока вы не зафиксируете строку или не вручную извлечете информацию из базы данных.

+0

Вы имеете в виду, что SQL Server 2008 мы не можем использовать @ GeneratedValue.Sequence или Table или Identity ??? Я решил, что мне нужно сначала сфотографировать (вставить вызов db для получения сгенерированного идентификатора), но моя цель - без вставки вызова, если я могу получить первичный идентификатор. –

+0

Возможно, вы, возможно, не указали, что в SQL Server для поддержки объекта SEQUENCE .... «Объекты последовательности используют специальные объекты базы данных для генерации идентификаторов. Объекты последовательности поддерживаются только в некоторых базах данных, таких как Oracle, DB2, и Postgres. " http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequision#Table_sequencing –

+0

Маркировка как ответ, SEQUENCE не поддерживается SQL Server –

11

Проблема в том, что вы используете IDENTITY id generation. Генерация идентификатора IDENTITY не может выполнять предварительное распределение, так как им требуется, чтобы INSERT генерировал идентификатор. TABLE и SEQUENCE поддерживают предварительное распределение поддержки, и я всегда рекомендую использовать их и никогда не использовать IDENTITY из-за этой проблемы и из-за производительности.

Вы можете активировать идентификатор, который будет сгенерирован при использовании генерации идентификатора IDENTITY, вызвав команду flush().

+0

Последовательность hmmm не работает для меня. Я изменил свою аннотацию в классе сущностей на: '@Id @SequenceGenerator (name =" seq ", sequenceName =" seq ") @GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "seq") ' –

+1

Затем после em.persist (myBean); int insertId = myBean.getId(); Этот getId() возвращает null ... я делаю что-то неправильно? –

+1

Это проблема синхронизации. JPA не вставляла данные при попытке получить значение id. Вы должны сбросить флажок, чтобы заставить его начать делать изменения в базе данных. Впоследствии у вас есть идентификатор. Лучше будет то, что JPA делает модификации на db, когда вы вызываете getId(). –

6

просто сделать это:

public void create(T entity) { 
    getEntityManager().persist(entity); 
    getEntityManager().flush(); 
    getEntityManager().refresh(entity); 
} 

После освежения лица вы имеете поле идентификатора с правильным значением.

+3

Причина добавления 'flush()' заключается в том, что 'persist()' явно не гарантированно сгенерировал '@ GeneratedValue', но он должен быть сгенерирован в или перед' flush() '. См. Этот вопрос: http://stackoverflow.com/questions/9087848/when-does-the-jpa-set-a-generatedvalueid – Raedwald

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

  • Нет связанных вопросов^_^