2015-02-03 12 views
8

Używanie Spring Data + hibernacja, Hibernate jest skonfigurowany do automatycznego tworzenia schematu. Jednak w przypadku zgłaszania wyjątku jest zgłaszany (patrz poniżej).Dane sprężyny + hibernacja używa niewłaściwej nazwy kolumny

Wygląda na to, że nazwa kolumny użyta podczas automatycznego tworzenia schematu różni się od nazwy kolumny zapytania.

Jeśli skonfiguruję LocalSessionFactoryBean do użycia strategii nazewnictwa, problem zniknie, a test zadziała.

Czy to błąd? czy coś nie rozumiem?

Konfiguracja znajduje się poniżej.

[Edytuj] Zgodnie z logiem poniżej wyświetlany jest komunikat ERROR: column datum0_.datum_id does not exist. Jednak kolumna jest faktycznie nazwany datumId, jak widać z zalogowanego 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> 

(edit) Wyjście + wyjątek:

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

sprężyny domyślny nazewnictwo będzie mapować 'datumId' do kolumny o nazwie' datum_id'. Jeśli chcesz, aby twoja kolumna używała innej nazwy, po prostu dodaj adnotację, aby to powiedzieć: '@Column (name =" datumId ")'. – Steve

+1

Zarysuj ... prawdopodobnie będziesz musiał zrobić to '@Column (name =" datumid ")'. Jeśli użyjesz opcji mixed case, "SpringNamingStrategy" zignoruje nazwę, którą podasz, i wstawi znaki podkreślenia, niezależnie od tego, czy chcesz, czy nie. – Steve

Odpowiedz

5

Domyślnie Wiosna Boot wykorzystuje org.springframework.boot.orm.jpa.SpringNamingStrategy.

Hibernate NamingStrategy, zgodnie ze wiosennymi zalecanymi konwencjami nazewnictwa.

Ta strategia nazewnictwa po prostu bierze nazwę pola i dedukuje nazwę kolumny opartą tylko na tym, zastępując wielbłądzie znakiem podkreślenia. Nie wysłano wyjątku, ale na podstawie tego Hibernacji prawdopodobnie zapytano o kolumnę datum_id.

Related issue raised on Spring boot project

+0

Przepraszamy, brakowało wyjątku, ale dodaliśmy go teraz. –

+0

Tak, ponieważ myślałem, że 'datum_id' jest tym, czego szuka Hibernate. W każdym razie, biorąc pod uwagę, że jest to domyślne zachowanie, dlatego musisz określić strategię nazewnictwa, jeśli domyślne ustawienie nie jest tym, czego potrzebujesz. –

+0

Springboot jest czysty, ponieważ automatyzuje to. Ale trochę denerwujące, że wymaga nadmiernego logowania, aby wiedzieć, co przyniósł i dlaczego ... Nie jestem pewien, czy to oszczędność czasu lub marnowanie więcej czasu. – Zombies

5
SpringNamingStrategy extends ImprovedNamingStrategy 

więc stosować poniżej:

znalazłem problem to jest w ImprovedNamingStrategy jeśli chcesz go rozwiązać bez szczegółów używać DefaultNamingStrategy zamiast ImprovedNamingStrategy jak poniżej w pliku właściwości

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

Szczegóły: Istnieją dwie metody w interfejsie interfejsu NamingStrategyToColumnNa me i columnName, pierwszy wywołany, jeśli nie określiłeś nazwy w @Column, a drugi został wywołany, jeśli określisz nazwę w @Column.

w ImprovedNamingStrategy zmienia nazwę z wielbłąda na _, natomiast w DefaultNamingStrategy zwraca nazwę tak jak w 2. metodzie, co jest moim zdaniem prawidłowym zachowaniem.

1

Wyliczyłem to.

Użyj DefaultNamingStrategy i odcisków w adnotacjach @Column.

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

i

@Column(name = "`datumId`") 
private int datumId; 
Powiązane problemy