Hibernate 不会自动增加实体 { Country } 的 id(使用 h2 数据库)

Hibernate doesn't auto increment id of entity { Country } ( using h2 data base )

我正在尝试使用 HibernateTemplate 将一些数据插入到 H2 数据库中,但我不知道为什么 Hibernate 不自动增加实体 { Country } 的 ID。 (该项目包含运行应用程序所需的所有依赖项,spring 依赖项,休眠依赖项,...)

错误信息:

Jan 07, 2022 9:46:43 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 5.6.3.Final
Jan 07, 2022 9:46:43 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
Jan 07, 2022 9:46:44 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table if exists continent CASCADE 
Hibernate: drop table if exists country CASCADE 
Hibernate: create table continent (continent_id integer generated by default as identity, code varchar(40) not null, name varchar(40) not null, primary key (continent_id))
Hibernate: create table country (id integer generated by default as identity, code varchar(20) not null, devise varchar(20) not null, greetings varchar(20) not null, name varchar(40) not null, continent_id integer, primary key (id))
Hibernate: alter table continent add constraint UK_absgp10b2mechi5a14a52oej3 unique (code)
Hibernate: alter table continent add constraint UK_a3ha82cpgf40ee95robng6ml8 unique (name)
Hibernate: alter table country add constraint UK_5s4ptnuqtd24d4p9au2rv53qm unique (code)
Hibernate: alter table country add constraint UK_llidyp77h6xkeokpbmoy710d4 unique (name)
Hibernate: alter table country add constraint FKpymfsgrl32dy3gtl9r7rykkjg foreign key (continent_id) references continent
Jan 07, 2022 9:46:45 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
        -----------------------------------------------------------
        |   -Pour l'ajout d'un nouveau pays tapper            [1] |
        |   -Pour lister les informations d'un pays, tapper   [2] |
        |   -Pour supprimer un pays, tapper                   [3] |
        |   -Pour modifier des informations d'un pays, tapper [4] |
        |   -Pour lister tous les pays d'un continent, tapper [5] |
        |   -Pour sortir de l'application tapper              [0] |
        -----------------------------------------------------------
        =====>1
        Ajouter un nouveau pays (code,nom,devise,salutation): 
        uk,united_kingdom,GBP,Hello,EU
        Hibernate: select country0_.id as id1_1_, country0_.code as code2_1_, country0_.continent_id as continen6_1_, country0_.devise as devise3_1_, country0_.greetings as greeting4_1_, country0_.name as name5_1_ from country country0_ where country0_.code=?
        Hibernate: select continent0_.continent_id as continen1_0_, continent0_.code as code2_0_, continent0_.name as name3_0_ from continent continent0_ where continent0_.code=?
        Hibernate: insert into country (id, code, continent_id, devise, greetings, name) values (null, ?, ?, ?, ?, ?)
        Jan 07, 2022 9:46:50 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
        WARN: SQL Error: 23502, SQLState: 23502
        Jan 07, 2022 9:46:50 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
        ERROR: NULL not allowed for column "ID"; SQL statement:
        insert into country (id, code, continent_id, devise, greetings, name) values (null, ?, ?, ?, ?, ?) [23502-204]

实体

    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    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 lombok.Data;
    
    @Entity
    @Data
    @Table(name="country")
    public class Country {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        @Column( unique = true, nullable = false, length = 40)
        private String name;
        @Column( unique = true, nullable = false, length = 20)
        private String code;
        @Column( unique = false, nullable = false, length = 20)
        private String devise;
        @Column( unique = false, nullable = false, length = 20)
        private String greetings;
        @ManyToOne(cascade = CascadeType.REFRESH , fetch = FetchType.EAGER)
        @JoinColumn(name = "continent_id")
        private Continent continent;
    }

休眠配置

使用注释的 Hibernate 配置

    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp2.BasicDataSource;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.orm.hibernate5.HibernateTemplate;
    import org.springframework.orm.hibernate5.HibernateTransactionManager;
    import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @Configuration
    @EnableTransactionManagement
    public class HibernateConf {
    
        @Bean
        public LocalSessionFactoryBean sessionFactory() {
            LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
            sessionFactory.setDataSource(dataSource());
            sessionFactory.setPackagesToScan("app");
            sessionFactory.setHibernateProperties(hibernateProperties());
    
            return sessionFactory;
        }
    
        @Bean("dataSource")
        public DataSource dataSource() {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setDriverClassName("org.h2.Driver");
            dataSource.setUrl("jdbc:h2:mem:db;");
    
            return dataSource;
        }
    
        @Bean
        public PlatformTransactionManager hibernateTransactionManager() {
            HibernateTransactionManager transactionManager = new HibernateTransactionManager();
            transactionManager.setSessionFactory(sessionFactory().getObject());
            [enter image description here][1]return transactionManager;
        }
    
        @Bean
        public HibernateTemplate getHibernateTemplate() {
            HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory().getObject());
            return hibernateTemplate;
        }
    
        private final Properties hibernateProperties() {
            Properties hibernateProperties = new Properties();
            hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
            hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
            hibernateProperties.setProperty("hibernate.show_sql", "true");
    
            return hibernateProperties;
        }
    }

DAO

DAO 层。 当我调用 addCountry 方法时抛出异常..

@Repository
    public class CountryDAOImpl implements CountryDAO {
        @Autowired
        private SessionFactory sessionFactory;
        @Autowired
        private HibernateTemplate hibernateTemplate;

        @Override
        public Country addCountry(Country country) {
            hibernateTemplate.save(country);
            System.out.println(country.toString());
            return country;
        }
    }

  

此问题已在 Hibernate ORM 5.6 中修复。5.Final,升级到此版本或任何更新版本是修复它的最佳方法。以下信息适用到旧版本。

这是 Hibernate ORM 的一个已知问题:HHH-14985,它为 H2 1.x 接受的 H2 生成无效的 SQL,默认情况下不被 H2 2.x。它已经在 Hibernate ORM 的源代码中得到修复,因此您需要等待它的下一个版本才能尝试使用 H2 2.0。

您可以尝试将 ;MODE=LEGACY 附加到 H2 的 JDBC URL 作为临时解决方法,在这种模式下,这些无效尝试将 NULL 值插入身份具有隐式 NOT NULL 约束的列不会产生此错误。

不幸的是,您可能 运行 遇到其他一些不兼容问题。在这种情况下,您需要降级到 H2 1.4.200(并删除 MODE 设置)。