MS SQL Server 2008 R2 IDENTITY 列的 JPA 注释

JPA annotation for MS SQL Server 2008 R2 IDENTITY column

我想知道正确的 JPA 注释设置来处理 MS Server 2008 R2 IDENTITY 列。

MS Server 2008 R2 (RTM) 不支持 SEQUENCE,但是当我通过原始 sql.

测试时,IDENTITY 会自动递增

但是,通过 JPA,我无法通过任何策略(IDENTITY、AUTO、TABLE)在 @GeneratedValue 注释上工作,并且我不允许更改 DB 模式,因为它是其他模式。我没有尝试使用 SEQUENCE,因为没有序列。

DB Table 模式

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: 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 列,但随后休眠不高兴不包括如下所示的 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 上设置休眠方言。将 org.hibernate.dialect.SQLServer2008Dialect 设置为休眠方言后,GenerationType.IDENTITY 工作正常,正如 Neil 提到的那样。

下面是我的spring数据配置和application.properties。 仅供参考,我有多个数据源,一个是供内部使用的 H2 嵌入式数据源,另一个是用于远程数据访问的 MS SQL 2008 服务器,我遇到了问题。

Spring MS SQL 2008 服务器的数据配置

@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 (?, ?)