Почему JPA persist() не генерирует первичный идентификатор с автоматическим приращением?
Я использую JPA toplink-essential и SQL Server 2008
Моя цель - получить значение первичного ключа с автоинкрементом данных, которые будут вставлены в таблицу. Я знаю, что в JDBC есть метод, подобный getInsertedId(), который дает вам идентификатор первичного идентификатора с автоинкрементом (но это после выполнения инструкции вставки)
В 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 :(
3 ответа
Мы также используем SQL Server 2008, и он никогда не работал для меня, поэтому я всегда выполняю отдельный запрос "SELECT @@IDENTY"
чтобы получить вставленный идентификатор.
Причина, которую я обнаружил в сети, заключалась в том, что автоматический идентификатор (IDENTITY) управляется базой данных и никогда не извлекается в Entity до тех пор, пока вы не зафиксируете строку или не получите информацию из базы данных вручную.
Проблема в том, что вы используете генерацию идентификатора IDENTITY. Генерация идентификатора IDENTITY не может выполнить предварительное распределение, так как для этого требуется INSERT. Генерация идентификаторов TABLE и SEQUENCE поддерживает предварительное распределение, и я всегда рекомендую использовать их, и никогда не использовать IDENTITY из-за этой проблемы и из-за производительности.
Вы можете инициировать создание идентификатора при использовании генерации идентификатора IDENTITY, вызвав flush().
Просто сделайте это:
public void create(T entity) {
getEntityManager().persist(entity);
getEntityManager().flush();
getEntityManager().refresh(entity);
}
После обновления сущности у вас есть поле ID с правильным значением.