2015-02-03 3 views
8

Использование Spring Data + hibernate, Hibernate настроен на автоматическое создание схемы. Однако при запросе исключения генерируется (см. Ниже).Данные Spring + hibernate используют неправильное имя столбца

Похоже, что имя столбца, используемое при создании автоматической схемы, отличается от имени столбца для запроса.

Если я настраиваю LocalSessionFactoryBean, чтобы использовать стратегию именования, проблема исчезает, и тест работает.

Это ошибка? или я что-то не понимаю?

Установка приведена ниже.

[Изменить] В соответствии с журналом под сообщением ERROR: column datum0_.datum_id does not exist присутствует. Однако столбец на самом деле называется datumId, как можно видеть из вошедшего SQL:

create table Datum (
    datumId int4 not null, 
    value varchar(255), 
    primary key (datumId) 
) 

Application.java:

package test; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.context.ConfigurableApplicationContext; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.ImportResource; 

@Configuration 
@ImportResource("classpath:Application.xml") 
@EnableAutoConfiguration 
public class Application { 
    static Log log = LogFactory.getLog(Application.class); 

    public static void main(String[] args) throws Exception { 
     ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); 
     DatumRepository repository = context.getBean(DatumRepository.class); 
     repository.findAll(); 
    } 
} 

Datum.java:

package test; 

import javax.persistence.*; 

@Entity 
public class Datum { 
    @Id 
    @GeneratedValue 
    private int datumId; 

    @Column 
    private String value; 

    public int getDatumId() { 
     return datumId; 
    } 

    public void setDatumId(int datumId) { 
     this.datumId = datumId; 
    } 

    public String getValue() { 
     return value; 
    } 

    public void setValue(String value) { 
     this.value = value; 
    } 
} 

DatumRepository .java:

package test; 

import org.springframework.data.repository.CrudRepository; 

public interface DatumRepository extends CrudRepository<Datum, Integer> { 
} 

Application.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://www.springframework.org/schema/beans" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
          http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> 

    <!--Searches for @Configuration classes and stereotypes--> 
    <context:component-scan base-package="test" /> 

    <!--Searches for @Autowired/@Inject--> 
    <context:annotation-config /> 

    <!-- For creation of repositories --> 
    <!--<jpa:repositories base-package="test" />--> 

    <!--Data source--> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="org.postgresql.Driver"/> 
     <property name="url" value="jdbc:postgresql://localhost/nexus"/> 
     <property name="username" value="nexus"/> 
     <property name="password" value="nexus"/> 
    </bean> 

    <!-- Hibernate --> 
    <bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="packagesToScan" value="test" /> 
     <!--<property name="namingStrategy"><ref bean="naming" /></property>--> 

     <property name="hibernateProperties"> 
      <value> 
       hibernate.hbm2ddl.auto=create-drop 
       hibernate.show_sql=true 
       hibernate.format_sql=true 
      </value> 
     </property> 
    </bean> 

    <bean id="naming" class="org.hibernate.cfg.ImprovedNamingStrategy"></bean> 
</beans> 

pom.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>test</groupId> 
    <artifactId>test1</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.2.1.RELEASE</version> 
    </parent> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.postgresql</groupId> 
      <artifactId>postgresql</artifactId> 
      <version>9.3-1100-jdbc41</version> 
     </dependency> 

     <dependency> 
      <groupId>commons-dbcp</groupId> 
      <artifactId>commons-dbcp</artifactId> 
      <version>1.4</version> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 

    <repositories> 
     <repository> 
      <id>spring-releases</id> 
      <url>https://repo.spring.io/libs-release</url> 
     </repository> 
    </repositories> 

    <pluginRepositories> 
     <pluginRepository> 
      <id>spring-releases</id> 
      <url>https://repo.spring.io/libs-release</url> 
     </pluginRepository> 
    </pluginRepositories> 

</project> 

(редактирование) выход + исключение:

2015-02-03 13:49:14.697 INFO 3515 --- [lication.main()] test.Application       : Starting Application on desktop with PID 3515 (/home/breamec/src/test1/target/classes started by breamec in /home/breamec/src/test1) 
2015-02-03 13:49:14.747 INFO 3515 --- [lication.main()] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]5b525b5f: startup date [Tue Feb 03 13:49:14 GMT 2015]; root of context hierarchy 
2015-02-03 13:49:15.232 INFO 3515 --- [lication.main()] o.s.b.f.xml.XmlBeanDefinitionReader  : Loading XML bean definitions from class path resource [Application.xml] 
2015-02-03 13:49:16.070 INFO 3515 --- [lication.main()] o.s.j.d.DriverManagerDataSource   : Loaded JDBC driver: org.postgresql.Driver 
2015-02-03 13:49:16.308 INFO 3515 --- [lication.main()] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 
2015-02-03 13:49:16.340 INFO 3515 --- [lication.main()] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ 
    name: default 
    ...] 
2015-02-03 13:49:16.454 INFO 3515 --- [lication.main()] org.hibernate.Version     : HHH000412: Hibernate Core {4.3.7.Final} 
2015-02-03 13:49:16.457 INFO 3515 --- [lication.main()] org.hibernate.cfg.Environment   : HHH000206: hibernate.properties not found 
2015-02-03 13:49:16.458 INFO 3515 --- [lication.main()] org.hibernate.cfg.Environment   : HHH000021: Bytecode provider name : javassist 
2015-02-03 13:49:16.683 INFO 3515 --- [lication.main()] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {4.0.5.Final} 
2015-02-03 13:49:17.202 INFO 3515 --- [lication.main()] org.hibernate.dialect.Dialect   : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect 
2015-02-03 13:49:17.218 INFO 3515 --- [lication.main()] o.h.e.jdbc.internal.LobCreatorBuilder : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException 
2015-02-03 13:49:17.355 INFO 3515 --- [lication.main()] o.h.h.i.ast.ASTQueryTranslatorFactory : HHH000397: Using ASTQueryTranslatorFactory 
2015-02-03 13:49:18.189 INFO 3515 --- [lication.main()] org.hibernate.dialect.Dialect   : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect 
2015-02-03 13:49:18.190 INFO 3515 --- [lication.main()] o.h.e.jdbc.internal.LobCreatorBuilder : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException 
2015-02-03 13:49:18.199 INFO 3515 --- [lication.main()] o.h.e.t.i.TransactionFactoryInitiator : HHH000399: Using default transaction strategy (direct JDBC transactions) 
2015-02-03 13:49:18.199 INFO 3515 --- [lication.main()] o.h.h.i.ast.ASTQueryTranslatorFactory : HHH000397: Using ASTQueryTranslatorFactory 
2015-02-03 13:49:18.211 INFO 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export 
Hibernate: 
    drop table Datum cascade 
2015-02-03 13:49:18.219 ERROR 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: drop table Datum cascade 
2015-02-03 13:49:18.219 ERROR 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : ERROR: table "datum" does not exist 
Hibernate: 
    drop sequence hibernate_sequence 
2015-02-03 13:49:18.221 ERROR 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: drop sequence hibernate_sequence 
2015-02-03 13:49:18.221 ERROR 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : ERROR: sequence "hibernate_sequence" does not exist 
Hibernate: 
    create table Datum (
     datumId int4 not null, 
     value varchar(255), 
     primary key (datumId) 
    ) 
Hibernate: 
    create sequence hibernate_sequence 
2015-02-03 13:49:18.230 INFO 3515 --- [lication.main()] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete 
2015-02-03 13:49:18.737 INFO 3515 --- [lication.main()] o.s.j.e.a.AnnotationMBeanExporter  : Registering beans for JMX exposure on startup 
2015-02-03 13:49:18.745 INFO 3515 --- [lication.main()] test.Application       : Started Application in 4.32 seconds (JVM running for 8.385) 
2015-02-03 13:49:18.961 WARN 3515 --- [lication.main()] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42703 
2015-02-03 13:49:18.961 ERROR 3515 --- [lication.main()] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: column datum0_.datum_id does not exist 
    Position: 8 
[WARNING] 
java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:418) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:231) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:214) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy51.findAll(Unknown Source) 
    at test.Application.main(Application.java:20) 
    ... 6 more 
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet 
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91) 
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2066) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1863) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:910) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) 
    at org.hibernate.loader.Loader.doList(Loader.java:2554) 
    at org.hibernate.loader.Loader.doList(Loader.java:2540) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) 
    at org.hibernate.loader.Loader.list(Loader.java:2365) 
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:497) 
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387) 
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:236) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103) 
    at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573) 
    at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449) 
    at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:67) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:289) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:442) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:427) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
    ... 14 more 
Caused by: org.postgresql.util.PSQLException: ERROR: column datum0_.datum_id does not exist 
    Position: 8 
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161) 
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890) 
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:560) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:302) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) 
    ... 45 more 
+1

Spring по умолчанию именование будет отображать 'datumId' в колонке под названием' datum_id'. Если вы хотите, чтобы ваш столбец использовал другое имя, просто запишите его так: '@Column (name =" datumId ")'. – Steve

+1

Поцарапайте это ... вам, вероятно, понадобится сделать его '@Column (name =" datumid ")'. Если вы используете смешанный случай, 'SpringNamingStrategy' будет игнорировать имя, которое вы предоставляете, и вставлять подчеркивания, хотите ли вы их или нет. – Steve

ответ

5

По умолчанию Spring использует загрузки org.springframework.boot.orm.jpa.SpringNamingStrategy.

Hibernate NamingStrategy, который следует за традиционными соглашениями об именах, рекомендованными весной.

Эта стратегия именования просто берет имя поля и выводит название столбца, основанное только на этом, заменяя случай верблюда символом подчеркивания. Вы не опубликовали исключение, но на основании этого Hibernate, возможно, запросили для столбца datum_id.

Related issue raised on Spring boot project

+0

Извините, пропустили исключение, но добавили сейчас. –

+0

Да, как я думал, 'datum_id' - это то, что ищет Hibernate. В любом случае, учитывая, что это поведение по умолчанию, именно по этой причине вам нужно указать стратегию именования, если по умолчанию это не то, что вам нужно. –

+0

Springboot опрятен тем, что он автоматически вводит это. Но это раздражает то, что он требует чрезмерного поиска в Google, чтобы узнать, что он принес и почему ... Не уверен, что это экономит время или тратит больше времени. – Zombies

5
SpringNamingStrategy extends ImprovedNamingStrategy 

поэтому применять ниже:

Я нашел этот вопрос он находится в ImprovedNamingStrategy, если вы хотите, чтобы решить эту проблему без деталей использовать DefaultNamingStrategy вместо ImprovedNamingStrategy, как показано ниже в файле свойств

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy 

Подробнее: В интерфейсе интерфейса NamingStrategy существует 2 методаToColumnNa me и columnName, сначала вызываемый, если вы не указали имя в @Column, а второе вызывали, если вы укажете имя в @Column.

в ImprovedNamingStrategy оба изменяют имя от верблюда до _ в то время как в DefaultNamingStrategy оно возвращает имя, поскольку оно находится во втором методе, который с моей точки зрения правильное поведение.

1

Выяснил это.

Используйте DefaultNamingStrategy и обратные ссылки в аннотации @Column.

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy 

и

@Column(name = "`datumId`") 
private int datumId; 

 Смежные вопросы

  • Нет связанных вопросов^_^