문제

I am developing a website using Spring+JPA+Hibernate. In the persistence configuration (JPA+Hibernate) I'm setting the HibernateJpaVendorAdapter's generateDdl attribute to true and in fact new entities correctly create the new table in the DB.

Once the table has been created, though, if I add an attribute to the entity, I'm expecting the HibernateJpaVendorAdapter to alter the table and add the column as well. This is not happening and it's strange because in the Java AbstractJpaVendorAdapter's setGenerateDdl method documentation there is: "Set whether to generate DDL after the EntityManagerFactory has been initialized, creating/updating all relevant tables."

JPA+Hibernate configuration:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${db.driverClassName}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
    <property name="showSql" value="${db.showSql}" />
    <property name="generateDdl" value="${db.generateDdl}" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter" ref="jpaAdapter" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
</bean>

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence
        xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
   http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">

    <persistence-unit name="m8tsPU" />
</persistence>

Am I doing something wrong?

도움이 되었습니까?

해결책

You can get a more fine-grained control over DDL generation by setting an appropriate Hibernate-specific property directly:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
     ...
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            ...
        </props>
    </property>
</bean>

Alternatively, you can use create-drop instead of update, since update may cause problems in some cases. Note, however, that automatic DDL update is not intended for production use.

다른 팁

Alternatively, you can also express the same properties using jpaPropertyMap:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     ...
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.hbm2ddl.auto" value="update"/>
                ...
            </map>
        </property>
</bean>

Maybe to late, but today I had the same problem when I was writing some tests for a legacy app.

The problem occurs not only when you use generateDdl property but also HSQL is used.

To solve it I changed the database from HSQL to H2 and the datasource from org.springframework.jdbc.datasource.DriverManagerDataSource to org.apache.commons.dbcp.BasicDataSource.

The spring-context.xml looks like:

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

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.h2.Driver"/>
        <property name="url" value="jdbc:h2:mem:test"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="dataSource" ref="dataSource"/>
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <tx:annotation-driven/>
...
</beans>

The persistence.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">

    <persistence-unit name="TestPU" transaction-type="RESOURCE_LOCAL">
        <properties>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        </properties>
    </persistence-unit>

</persistence>

I hope it helps.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top