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
设置)。
我正在尝试使用 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
设置)。