我从Spring Boot 1.5.9迁移到正常的Spring项目。
在application.properties
我已添加
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
我有一个配置类
@Configuration
public class HibernateJpaConfig {
private Map<String, String> properties = new HashMap<String, String>();
public HibernateJpaConfig() {
properties.put("hibernate.hbm2ddl.auto", "create-drop");
}
@Bean
@Primary
public DataSource dataSource(){
DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:testdb");
dataSource.setUsername("sa"); dataSource.setPassword("");
return dataSource;
}
@Autowired
private DataSource dataSource;
@Autowired(required = false)
private PersistenceUnitManager persistenceUnitManager;
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(false);
adapter.setDatabase(Database.H2);
adapter.setDatabasePlatform("H2");
adapter.setGenerateDdl(true);
return adapter;
}
@Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter) {
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
jpaVendorAdapter, properties,
this.persistenceUnitManager);
builder.setCallback(null);
return builder;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
Map<String, Object> vendorProperties = new LinkedHashMap<String, Object>();
vendorProperties.putAll(properties);
return factoryBuilder.dataSource(this.dataSource).packages("com.fabio.springmvc.domain")
.properties(vendorProperties).jta(false).build();
}
}
当我运行项目时,我遇到以下错误(我已添加警告,因为它似乎与问题相关)
2018-01-07 06:03:34.542 WARN 17268 --- [ restartedMain] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/fabio/springmvc/config/HibernateJpaConfig.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
2018-01-07 06:03:34.545 INFO 17268 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2018-01-07 06:03:34.557 INFO 17268 --- [ restartedMain] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-01-07 06:03:34.564 ERROR 17268 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/fabio/springmvc/config/HibernateJpaConfig.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at com.fabio.springmvc.SpringmvcApplication.main(SpringmvcApplication.java:17) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.9.RELEASE.jar:1.5.9.RELEASE]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:382) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 21 common frames omitted
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.fabio.springmvc.domain.Customer column: addressLine1 (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:830) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:848) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:844) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:870) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:605) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.RootClass.validate(RootClass.java:265) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:443) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
... 28 common frames omitted
配置类基于Spring boot 1.3的课程,这里我使用的是1.5.9,我不知道为什么会遇到这个问题。
编辑客户重复列
@Entity
public class Customer extends AbstractDomainClass{
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
@Embedded
private Address billingAddress;
@Embedded
private Address shippingAddress;
// getters setters
}
地址类
@Embeddable
public class Address {
private String addressLine1;
private String addressLine2;
private String city;
private String state;
private String zipCode;
// getters setters
}
答案 0 :(得分:2)
出现此问题是因为您具有以下映射:
@Entity
public class Customer extends AbstractDomainClass {
//other attributes...
@Embedded
private Address billingAddress;
@Embedded
private Address shippingAddress;
}
在这里,Hibernate将尝试做的是在表的列中映射@Embedded
类的属性。也就是说,它会将Address#addressLine1
从属性Address billingAddress
映射到表addressLine1
中的列customer
。属性billingAddress
和类Address
的其他字段也会发生类似情况。然后,它会对Address shippingAddress
执行相同操作,也就是说,它会将Address#addressLine1
的{{1}}映射到表shippingAddress
中的列addressLine1
。这是例外的原因。
由于这更像是设计问题,而不是代码中的问题,我建议采用一些方法来解决它。
在表格中为所有字段添加不同的列,并将每个列映射到类中的特定属性。这是一个基本的例子:
你桌子的DDL(使用我能想到的最常见的sql)。
customer
使用CREATE TABLE customer (
id INT NOT NULL,
billingAddressLine1 VARCHAR(200) NOT NULL,
shippingAddressLine1 VARCHAR(200) NOT NULL,
-- other columns...
PRIMARY KEY(id)
);
的{{1}}属性的Hibernate映射:
@Embedded
不使用@AttributeOverrides
表中的列,而是使用名为@Entity
public class Customer extends AbstractDomainClass {
//other attributes...
@Embedded
@AttributeOverrides(
@AttributeOverride(
name = "addressLine1",
column = @Column(name = "billingAddressLine1"),
)
//do similar for the other attributes...
)
private Address billingAddress;
@Embedded
@AttributeOverrides(
@AttributeOverride(
name = "addressLine1",
column = @Column(name = "shippingAddressLine1")
)
//do similar for the other attributes...
)
private Address shippingAddress;
}
的单独表和名为customer
的列(或您喜欢的名称)来存储地址顾客。
你桌子的DDL(使用我能想到的最常见的sql)。
address
类的Hibernate映射(不是addressType
):
CREATE TABLE customer (
id INT NOT NULL,
-- other columns...
PRIMARY KEY(id)
);
CREATE TABLE address (
id INT NOT NULL,
addressType INT NOT NULL,
customer_id INT NOT NULL,
addressLine1 VARCHAR(200) NOT NULL,
-- other columns...
PRIMARY KEY(id),
FOREIGN KEY (customer_id) REFERENCES customer(id)
);