我想知道正确的 JPA 注释设置来处理 MS Server 2008 R2 IDENTITY 列。
MS Server 2008 R2 (RTM) 不支持 SEQUENCE,但当我通过原始 sql 测试时,IDENTITY 会自动递增。
但是,通过 JPA,我无法通过 @GeneratedValue 注释上的任何策略(IDENTITY、AUTO、TABLE)使其工作,并且我不允许更改 DB 模式,因为它是其他模式。我没有尝试使用 SEQUENCE,因为没有序列。
数据库表架构
CREATE TABLE [dbo].[invoice_header](
[invoice_id] [int] IDENTITY(1,1) NOT NULL,
[ApprovalDate] [datetime] NULL,
[ApproverUserName] [nvarchar](50) NULL,
CONSTRAINT [PK_invoice_header] PRIMARY KEY CLUSTERED
(
[invoice_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
JPA 注解
@Entity
@Table(name = "invoice_header")
public class InvoiceHeader {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column(name="invoice_id")
private Long invoiceId;
hibernate 错误
Hibernate: insert into tbl_acct_textura_invoice_header (invoice_id, ApprovalDate, ApproverUserName) values (null, ?, ?)
2015-06-16 11:12:24.149 ERROR 7157 --- [tp1024240671-18] o.h.engine.jdbc.spi.SqlExceptionHelper : DEFAULT or NULL are not allowed as explicit identity values.
由于在 Id 上传递 null 而失败。我可以通过 @Column 注释上的 insertable=false 和 updatable=false 使 HQL 在插入期间不包含 invoice_id 列,但是随后 hibernate 对不包含如下所示的 Id 列不满意。有什么建议吗?仅供引用,我正在使用 spring-data JpaRepository
在插入期间不包含 id 列时出现 Hibernate 错误
nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): ...InvoiceHeader
最佳答案
我刚刚发现我错过了在 LocalContainerEntityManagerFactoryBean 上设置 hibernate 方言。将 org.hibernate.dialect.SQLServer2008Dialect 设置为 hibernate 方言后,GenerationType.IDENTITY 工作正常,正如 Neil 提到的那样。
下面是我的spring数据配置和application.properties。 仅供引用,我有多个数据源,一个是供内部使用的 H2 嵌入式数据源,另一个是用于远程数据访问的 MS SQL 2008 服务器,我遇到了问题。
MS SQL 2008 服务器的 Spring Data 配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "adapterEntityManagerFactory",
transactionManagerRef = "adapterTransactionManager",
basePackages = {"com.textura.client.erp.database.repository"})
public class ErpRepositoryConfig {
@Autowired
JpaVendorAdapter jpaVendorAdapter;
@Value("${adapter.datasource.url}")
private String databaseUrl;
@Value("${adapter.datasource.username}")
private String username;
@Value("${adapter.datasource.password}")
private String password;
@Value("${adapter.datasource.hibernate.dialect}")
private String dialect;
public DataSource dataSource() {
return new DriverManagerDataSource(databaseUrl, username, password);
}
@Bean(name = "adapterEntityManager")
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
@Bean(name = "adapterEntityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", dialect); //"org.hibernate.dialect.SQLServer2008Dialect"
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.textura.client.erp.database.model");
lef.setPersistenceUnitName("adapterPersistenceUnit");
lef.setJpaProperties(properties);
lef.afterPropertiesSet();
return lef.getObject();
}
@Bean(name = "adapterTransactionManager")
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}
类路径中的 application.properties 文件
# database configuration
spring.datasource.url=jdbc:h2:file:~/internal;AUTO_SERVER=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.schema=schema.sql
spring.datasource.data=data.sql
spring.datasource.initialize=false
#spring.datasource.initialize=true only for first time to create table, after that switch to false
# JPA. Hibernate
spring.jpa.database=H2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
#spring.jpa.hibernate.ddl-auto=choose one of [create-drop, create, update, validate, none]
spring.jpa.hibernate.naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql=true
spring.data.jpa.repositories.enabled=true
# MS SQL Server 2008 datasource
adapter.datasource.url=jdbc:sqlserver://some.ip.address:1433;databaseName=Remote
adapter.datasource.username=sa
adapter.datasource.password=password
adapter.datasource.hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
在那之后,我看到了 GenerationType.IDENTITY 的魅力
Hibernate: insert into invoice_header (ApprovalDate, ApproverUserName) values (?, ?)
关于hibernate - MS SQL Server 2008 R2 IDENTITY 列的 JPA 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30874268/