休眠不会自动递增实体 { 国家 } 的 ID (使用 h2 数据库)



我正试图使用hibernate模板将一些数据插入H2数据库,但我不知道hibernate为什么不自动增加实体{Country}的id。(该项目包含运行应用程序所需的所有依赖项、spring依赖项、hibernate依赖项…(

错误消息:

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;
}

休眠配置

使用annotaions 的休眠配置

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中修复。最终,升级到此版本或任何更新版本是修复此问题的最佳方法。以下信息适用于旧版本。

这是Hibernate ORM:HHH-14985的一个已知问题,它为H2生成了无效的SQL,H2 1.x接受了该SQL,H2 2.x默认不接受该SQL。它已经在Hibernate ORM的源代码中修复,所以在尝试使用H2 2.0之前,您需要等待它的下一个版本。

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

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

最新更新