首页 > 解决方案 > 为什么在将记录插入表时休眠不为主键列选择数据库序列?

问题描述

我在搞乱我的 Spring Boot 应用程序。编写了一些代码将少量记录插入到我的 h2 数据库中的表(称为 STARS)中。

这是它的schema.sql

DROP TABLE IF EXISTS STAR;
CREATE TABLE STARS(
ID INT AUTO_INCREMENT PRIMARY KEY,
FIRST_NAME VARCHAR(25) NOT NULL,
LAST_NAME VARCHAR(25) NOT NULL
);

--STAR Sequence

drop sequence if exists STAR_SEQ;

create sequence STAR_SEQ
start with 500
increment by 100
minvalue 0
maxvalue 1000
nocycle;

实体类

package com.test.api.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.GeneratorType;

@Entity
@Table(name="star")
public class Star {
@Id
@SequenceGenerator(name="SEQ",sequenceName="STAR_SEQ",allocationSize=100)
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="SEQ")
private Long id;
private String first_name;
private String last_name;
public Star() {}
public Star(String first_name,String last_name) {
    this.first_name=first_name;
    this.last_name=last_name;
}
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public String getFirst_name() {
    return first_name;
}
public void setFirst_name(String first_name) {
    this.first_name = first_name;
}
public String getLast_name() {
    return last_name;
}
public void setLast_name(String last_name) {
    this.last_name = last_name;
}


}

应用程序属性

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
server.port=8081
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

SpringBootApplication.java

package com.test.api;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.test.api.model.Star;
import com.test.api.service.StarsService;

@SpringBootApplication
public class SpringbootapiApplication implements CommandLineRunner{
@Autowired
StarsService starService;
    public static void main(String[] args) {
        SpringApplication.run(SpringbootapiApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        starService.saveStar(new Star("Morgan","Freeman"));
        starService.saveStar(new Star("Brad","Pitt"));
        starService.saveStar(new Star("Tom","Cruise"));
        List<Star> allStars = starService.getAllStars();
        System.out.println("Size of elements:"+allStars.size());
        for(Star star:allStars)
            System.out.println(star.getFirst_name()+":"+star.getLast_name()+":"+star.getId());

    }

}

服务器启动日志

Hibernate: drop table star if exists
Hibernate: drop sequence if exists star_seq
Hibernate: create sequence star_seq start with 1 increment by 100
Hibernate: create table star (id bigint not null, first_name varchar(255), last_name varchar(255), primary key (id))
2019-11-16 23:43:19.733  INFO 13228 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2019-11-16 23:43:19.747  INFO 13228 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-11-16 23:43:20.245  WARN 13228 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2019-11-16 23:43:20.533  INFO 13228 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-11-16 23:43:20.957  INFO 13228 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2019-11-16 23:43:20.961  INFO 13228 --- [           main] com.test.api.SpringbootapiApplication    : Started SpringbootapiApplication in 6.785 seconds (JVM running for 8.566)
Hibernate: call next value for star_seq
Hibernate: call next value for star_seq
Hibernate: insert into star (first_name, last_name, id) values (?, ?, ?)
Hibernate: insert into star (first_name, last_name, id) values (?, ?, ?)
Hibernate: insert into star (first_name, last_name, id) values (?, ?, ?)
Hibernate: select star0_.id as id1_0_, star0_.first_name as first_na2_0_, star0_.last_name as last_nam3_0_ from star star0_
Size of elements:3
Morgan:Freeman:1
Brad:Pitt:2
Tom:Cruise:3

我期待 db 序列被拾取,日志应该像这样打印:

Morgan:Freeman:500
Brad:Pitt:600
Tom:Cruise:700

请帮我理解。谢谢。

标签: hibernatespring-data-jpasequence

解决方案


我已将 spring.jpa.hibernate.ddl-auto 的值设置为 create-drop。这意味着休眠将使用实体定义为我创建模式。它根本没有考虑 schema.sql 文件。它只是使用实体类本身给出的配置来创建序列。为了让我的表从序列中检索 id。我只是将 spring.jpa.hibernate.ddl-auto 的值关闭为 none。这将使 schema.sql 在不休眠生成任何数据库对象(如表/序列)的情况下执行。


推荐阅读