在Spring + Hibernate + JPA设置

时间:2016-11-24 14:19:10

标签: java spring hibernate jpa

我有这种奇怪的情况,当在测试环境中一切正常时,但是当部署在WildFly上时,entityManager由于某种原因找不到事务。 我已经检查了bean是否创建了两次 - 一次是在mvc中,一次是在核心上下文中 - 但是trace只出现一次。 在StackOverflow上尝试了几乎所有其他修复,但问题(与我希望EntityManager保存的数据不同)仍然存在。

也许你能在我的配置中发现一些我找不到的错误?

Hibernate java config(DataSource在另一个模块中初始化,切换到注释DS不做任何事情):

@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@EnableJpaRepositories(
        entityManagerFactoryRef = "user.management.entityManagerFactory",
        transactionManagerRef = "user.management.transactionManager")
public class HibernateConfiguration {
    private static final String PROPERTY_NAME_DATABASE_DRIVER = "org.postgresql.Driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "";
    private static final String PROPERTY_NAME_DATABASE_URL = "jdbc:postgresql://localhost:5432/postgres";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "postgres";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";

    @Resource
    private Environment env;

    @Autowired
    @Bean(name = "user.management.jpaDialect")
    HibernateJpaDialect getDialect() {
        return new HibernateJpaDialect();
    }

    @Autowired
    @Bean(name = "user.management.jpaVendorAdapter")
    HibernateJpaVendorAdapter getJpaVendorAdapter() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(Database.HSQL);
        vendorAdapter.setDatabasePlatform("org.hibernate.dialect.HSQLDialect");
        vendorAdapter.setGenerateDdl(false);
        return vendorAdapter;
    }

    @Autowired
    @Bean(name = "user.management.impl.repository.util.DbUtil")
    DbUtil getDbUtil(
            @Qualifier("DataSource")
                    DataSource dataSource
    ) {
        DbUtil dbUtil = new DbUtil(dataSource);
        return dbUtil;
    }

    @Autowired
    @Bean(name = "hibernate5AnnotatedSessionFactory")
    LocalSessionFactoryBuilder getLocalSessionFactoryBean(
            @Qualifier("DataSource")
                    DataSource dataSource
    ) {
        LocalSessionFactoryBuilder localSessionFactoryBean =
                new LocalSessionFactoryBuilder(dataSource);
        localSessionFactoryBean.scanPackages(
                "user.management.impl.repository.pojo"
        );
        localSessionFactoryBean.addProperties(getHibernateProperties());
        localSessionFactoryBean.buildSessionFactory();

        return localSessionFactoryBean;
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.show_sql", "false");
        properties.put("hibernate.current_session_context_class", "thread");
        properties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        return properties;
    }

    /*@Autowired
    @Bean(name = "user.management.dataSource")
    public DataSource getPooledDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(PROPERTY_NAME_DATABASE_DRIVER);
        dataSource.setUrl(PROPERTY_NAME_DATABASE_URL);
        dataSource.setUsername(PROPERTY_NAME_DATABASE_USERNAME);
        dataSource.setPassword(PROPERTY_NAME_DATABASE_PASSWORD);
        return dataSource;
    }*/

    @Autowired
    @Bean(name = "user.management.entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory(
            @Qualifier("DataSource")
                    DataSource dataSource
    ) {
        System.out.println("getEntityManagerFactory()");

        LocalContainerEntityManagerFactoryBean theEntityManager = new LocalContainerEntityManagerFactoryBean();
        theEntityManager.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
        theEntityManager.setPersistenceUnitName("umPersistenceUnit");
        theEntityManager.setDataSource(dataSource);
        theEntityManager.setPackagesToScan(
                "user.management.impl.repository.pojo",
        );
        theEntityManager.setJpaVendorAdapter(getJpaVendorAdapter());
        theEntityManager.setJpaDialect(getJpaDialect());
        theEntityManager.afterPropertiesSet();

        return theEntityManager;
    }

    @Autowired
    @Bean(name = "user.management.jpaDialect")
    public JpaDialect getJpaDialect() {
        return new HibernateJpaDialect();
    }

    @Autowired
    @Bean(name = "user.management.transactionManager")
    public JpaTransactionManager getTransactionManager(
            @Qualifier("user.management.entityManagerFactory")
                    EntityManagerFactory entityManagerFactory,
            @Qualifier("DataSource")
                    DataSource dataSource
    ) {
        JpaTransactionManager jpaTranstactionManager =
                new JpaTransactionManager(entityManagerFactory);
        jpaTranstactionManager.setDataSource(dataSource);
        jpaTranstactionManager.setJpaDialect(getJpaDialect());
        jpaTranstactionManager.setEntityManagerFactory(entityManagerFactory);
        jpaTranstactionManager.afterPropertiesSet();

        return jpaTranstactionManager;
    }

    //DAO Classes

    @Autowired
    @Bean(name = "user.management.userRepository")
    public UserRepository getUserDao(
            @Qualifier("cacheManager")
                    CacheManager cacheManager) {
        return new UserDaoImpl(getIdGenerator(), cacheManager);
    }

    @Autowired
    @Bean(name = "user.management.groupDao")
    public GroupRepository getGroupDao() {
        return new GroupDaoImpl(getIdGenerator());
    }

    @Autowired
    @Bean(name = "user.management.roleDao")
    public RoleRepository getRoleDao() {
        return new RoleDaoImpl(getIdGenerator());
    }

    @Autowired
    @Bean(name = "user.management.profileDao")
    public UserProfileRepository getProfileRepository() {
        return new UserProfileDaoImpl(getIdGenerator());
    }

    @Autowired
    @Bean(name = "user.management.impl.service.idgenerator.IdGenerator")
    public IdGenerator getIdGenerator() {
        return new IdGenerator();
    }

    @Autowired
    @Bean(name = "user.management.AuthenticatorRepositoryDAO")
    public AuthenticatorRepository getAuthenticationRepository() {
        return new AuthenticatorRepositoryDAO();
    }

    @Autowired
    @Bean(name = "user.management.dobLdapSourceRepository")
    public LdapSourceRepository getLdapSourceRepository() {
        return new LdapSourceRepositoryImpl();
    }

    @Autowired
    @Bean(name = "user.management.dobOpenIdAuthenticationProviderRepository")
    public OpenIdAuthenticationProviderRepository getOpenIdAuthenticationProviderRepository() {
        return new OpenIdAuthenticationProviderRepositoryDAO();
    }
}

服务java配置

@Configuration
public class UserManagementConfiguration {
    @Autowired
    @Bean(name = "user.management.services.UserService")
    public UserService getUserService(...) {
        return new UserServiceImpl(...);
    }
}

DAO

@Transactional(propagation = Propagation.REQUIRED)
public class UserDao implements UserRepository {

    public UserDao(...) {}

    @PersistenceContext(unitName = "umPersistenceUnit")
    private EntityManager entityManager;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void persistUser(@Nonnull MutableUser user) {
        entityManager.persist(user);
    }
}

服务

public class UserServiceImpl implements UserService {

    public UserServiceImpl(...);
    }


    @Override
    @Transactional
    public void persistUser(@Nonnull User user) {
        userDAO.persistUser(mutableUser);
    }
}

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             version="1.0">
    <persistence-unit name="umPersistenceUnit">
        <!-- Forces Hibernate to work with old-style annotations -->
        <properties>
            <property name="hibernate.id.new_generator_mappings" value="false"></property>
        </properties>
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <class>user.management.impl.repository.pojo.User</class>
    </persistence-unit>
</persistence>

Spring config.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:annotation-config/>

    <tx:annotation-driven transaction-manager="user.management.transactionManager"/>

    <bean class="user.management.config.UserManagementConfiguration"/>
    <bean class="user.management.config.HibernateConfiguration"/>

    </bean>
</beans>

测试配置相同,仅使用不同的dataSourcejdbc.driver连接到内存中的h2。 我已经尝试过了:

  1. 使用<tx:annotation-driven>并指向正确的transactionManagerFactory

  2. transaction-type="RESOURCE_LOCAL"

  3. 中删除persistence.xml
  4. @Transactional添加到DaoService类中的特定方法。

  5. 检查entityManagerFactory仅在服务器启动时加载一次

  6. 调试服务器以查看是否调用了其他一些entityManager。我可以在其属性中清楚地看到我的持久性单元和限定符。

  7. 当我试图谷歌解决这个问题时,可能会出现一些其他的小修正。

  8. 当我部署像此处发布的代码时,我可以看到日志中没有错误等。添加entitymanager.flush()后,它变为javax.persistence.TransactionRequiredException: no transaction is in progress

1 个答案:

答案 0 :(得分:1)

为persistence.xml提供transaction-type="JTA"明确修复了问题,实体正在成功地持久保存到数据库。