Столбец Oracle 12c Identity с использованием Hibernate 5
Я пытаюсь использовать функцию столбца Oracle 12c Identity с Hibernate-5.0.0.CR4
, Я использовал следующие свойства в Spring boot application.properties:
spring.jpa.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
spring.datasource.driverClassName=oracle.jdbc.OracleDriver
Из исходного кода Oracle12cDialect
Казалось, он поддерживает идентичность столбца. Но я получаю следующую ошибку при попытке вставить запись в таблицу с именем user_preferences
:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.envers.Audited;
import org.hibernate.envers.RelationTargetAuditMode;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Entity
@Table(name = "user_preferences")
@Data
@JsonIgnoreProperties(value = { "prefId" })
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
public class UserPreference {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "pref_id")
private Long prefId;
@Column(nullable = false)
private String key;
@Column(nullable = false)
private String preference;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public UserPreference() {
}
public UserPreference(String key, String preference, User user) {
this.key = key;
this.preference = preference;
this.user = user;
}
}
Исключение, которое я получаю:
java.sql.SQLException: Invalid column type: getLong not implemented for class oracle.jdbc.driver.T4CRowidAccessor
at oracle.jdbc.driver.GeneratedAccessor.getLong(GeneratedAccessor.java:436)
at oracle.jdbc.driver.GeneratedStatement.getLong(GeneratedStatement.java:228)
at oracle.jdbc.driver.GeneratedScrollableResultSet.getLong(GeneratedScrollableResultSet.java:564)
at org.hibernate.id.IdentifierGeneratorHelper.get(IdentifierGeneratorHelper.java:113)
at org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity(IdentifierGeneratorHelper.java:73)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:88)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2730)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3300)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:474)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:179)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:163)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:198)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:317)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:272)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:109)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:774)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:747)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:752)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:344)
at com.sun.proxy.$Proxy106.persist(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291)
at com.sun.proxy.$Proxy106.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:433)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:436)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:421)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:393)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$DefaultMethodInvokingMethodInterceptor.invoke(RepositoryFactorySupport.java:506)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy117.save(Unknown Source)
at nl.yestelecom.phoenix.user.preference.UserPreferenceService.saveUserPreference(UserPreferenceService.java:45)
at nl.yestelecom.phoenix.controller.UserController.saveUserPreference(UserController.java:34)
Пожалуйста, дайте мне знать, если есть способ использовать столбец идентичности без использования последовательностей базы данных.
2 ответа
Похоже, что Hibernate 5.0.X выполняет запрос, пытаясь получить значение идентификатора из базы данных, когда вы указываете GenerationType.IDENTITY. Это значение извлекается из Java ResultSet с использованием соответствующего getXXX в зависимости от типа, который вы использовали для объявления своего идентификатора. В моем случае сработает resultSet.getString(columnIndex) или resultSet.getRowId(columnIndex), но RowId не может использоваться в компоненте JPA.
Если вы попытаетесь изменить его идентификатор на строку, это должно сработать, даже если для меня это выглядит как ошибка:
@Id
@Column(name="PRD_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private String prdId;
Вы можете сделать это, как показано ниже:
CREATE TABLE identity_test_tab (идентификатор: NUMBER, созданный по умолчанию в качестве идентификатора, описание VARCHAR2 (30));
SQL> INSERT INTO identity_test_tab (description) VALUES ('Просто ОПИСАНИЕ');
1 ряд создан.
SQL> INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID = 999 и DESCRIPTION');
1 ряд создан.
SQL> INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID = NULL and DESCRIPTION'); INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID = NULL and DESCRIPTION') * ОШИБКА в строке 1: ORA-01400: невозможно вставить NULL в ("TEST"."IDENTITY_TEST_TAB"."ID")
так как всегда столбец идентичности должен иметь значение не нуль