在将JPA2与Hibernate 4和Spring 3一起使用时,如何设置SessionFactory?

时间:2014-01-12 22:58:48

标签: java spring hibernate jpa

在控制器内部,当我调用.persist时,我的代码不会持久存在。我还包括我的AppConfig以供参考以及我的gradle依赖项。这完全在Tomcat7上。

的persistence.xml

<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_2_0.xsd"
             version="2.0">
    <persistence-unit name="main">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/dirtylibs"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="password"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

摇篮

testCompile group: 'junit', name: 'junit', version: '4.11'
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
compile group: 'org.springframework', name: 'spring-webmvc', version: '3.2.5.RELEASE'
compile group: 'org.springframework', name: 'spring-orm', version: '3.2.5.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '4.3.0.Final'
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.0.Final'
runtime group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.3.0'
runtime group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.3.0'
runtime group: 'mysql', name:'mysql-connector-java', version: '5.1.26'

的AppConfig

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = AppConfig.class)
@EnableTransactionManagement
public class AppConfig {


    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class.forName("com.mysql.jdbc.Driver").newInstance(); //This is some wierdness I needed to do because the mysql driver wasn't being picked up correctly
        LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        return localContainerEntityManagerFactoryBean;
    }
}

我的控制器

@Controller
public class SampleController {

    @PersistenceContext
    EntityManager entityManager;
    @RequestMapping("home/test/{id}")
    @ResponseBody
    public List<Integer> getMessagesTest(@PathVariable Integer id) {
        Phrase phrase = new Phrase();
        entityManager.persist(phrase);
        return Arrays.asList(phrase.getId());
    }

}

根据

EntityManager persist() method does not insert record to database => SEVERE: javax.persistence.TransactionRequiredException

要使用实体管理器将数据保存到数据库,我需要将其包含在事务中,该事务将在事务结束时为我调用.flush()。这意味着我需要将@Transaction添加到我的控制器,我做了。现在它看起来像这样。

@RequestMapping("home/test/{id}")
@ResponseBody
@Transactional
public List<Integer> getMessagesTest(@PathVariable Integer id) {
    Phrase phrase = new Phrase();
    entityManager.persist(phrase);
    return Arrays.asList(phrase.getId());
}

http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/orm/hibernate4/HibernateTransactionManager.html

一旦我这样做,我得到以下例外。

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined

好的,没问题。看起来Hibernate 4 HibernateTransactionManager会完成这项工作。一旦我开始在AppConfig中配置HibernateTransactionManager,我意识到我还需要一个SessionFactory。

我对创建SessionFactory的所有选项以及它与我的persistence.xml的关系非常困惑

我的主要问题是在目前的设置下,我应该如何构建会话工厂?

查看Spring文档,看起来我必须重复我的persistence.xml中的所有信息,这对我来说似乎是错误的。 http://docs.spring.io/spring/docs/3.0.x/reference/orm.html#orm-hibernate

我们非常感谢任何帮助,包括对当前设置的批评。我真的想坚持使用Java配置,并尽可能避免使用XML。我甚至想离开这里描述的persistence-config.xml,但是我想等到它工作之后再尝试它。

http://spring.io/blog/2011/06/10/spring-3-1-m2-configuration-enhancements/

1 个答案:

答案 0 :(得分:0)

Bozho在Best Way to Inject Hibernate Session by Spring 3的帖子给了我所需要的信息,让它们全部捆绑在一起。我仍然没有弄清楚我是否需​​要persistence.xml,但现在我正在将实体记录到数据库中。

我的新AppConfig现在看起来像这样

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
    hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
    hibernateJpaVendorAdapter.setShowSql(true);
    localContainerEntityManagerFactoryBean.setJpaVendorAdapter(hibernateJpaVendorAdapter);
    return localContainerEntityManagerFactoryBean;
}

@Bean
BasicDataSource basicDataSource() {
    BasicDataSource basicDataSource = new BasicDataSource();

    basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
    basicDataSource.setUrl("jdbc:mysql://localhost:3306/dirtylibs");
    basicDataSource.setUsername("root");
    basicDataSource.setPassword("password");

    return basicDataSource;
}


@Bean
JpaTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean) {
    JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
    jpaTransactionManager.setEntityManagerFactory(localContainerEntityManagerFactoryBean.getObject());
    return jpaTransactionManager;
}

我不得不为来自Apache的BasicDataSource引入另一个依赖项。这是Gradle坐标。

compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'