Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring JPA交易没有';t似乎被重用,连接池也在不断增长_Java_Hibernate_Spring Mvc_Jpa_Transactions - Fatal编程技术网

Java Spring JPA交易没有';t似乎被重用,连接池也在不断增长

Java Spring JPA交易没有';t似乎被重用,连接池也在不断增长,java,hibernate,spring-mvc,jpa,transactions,Java,Hibernate,Spring Mvc,Jpa,Transactions,我将Spring框架与Hibernate5和dbcp2一起使用。我们从直接使用hibernate切换到JPA。当我们这样做时,我们的应用程序停止工作 1)问题 连接池似乎不起作用或使用不正确:当我们监视数据库活动时,我们注意到连接的数量稳步增长 在我们的例子中,在控制器中接收REST请求,该控制器将细节传递给服务层。每个请求调用一次服务,并用@Transactional(readOnly=true)注释该服务。然后,服务通过DAO类访问数据来处理请求 在这种体系结构中,实际业务逻辑只应使用一个事

我将Spring框架与Hibernate5和dbcp2一起使用。我们从直接使用hibernate切换到JPA。当我们这样做时,我们的应用程序停止工作

1)问题

连接池似乎不起作用或使用不正确:当我们监视数据库活动时,我们注意到连接的数量稳步增长

在我们的例子中,在控制器中接收REST请求,该控制器将细节传递给服务层。每个请求调用一次服务,并用
@Transactional(readOnly=true)
注释该服务。然后,服务通过DAO类访问数据来处理请求

在这种体系结构中,实际业务逻辑只应使用一个事务,池中应使用一个JDBC连接。但是,跟踪和数据库统计数据显示,创建了更多的连接和事务

当请求结束时,许多到数据库的连接仍处于活动状态

通常应用程序会被卡住:

17:21:07,070 DEBUG [AbstractPlatformTransactionManager]:1020 - Resuming suspended transaction after completion of inner transaction
17:21:07,070 TRACE [TransactionSynchronizationManager]:272 - Initializing transaction synchronization
对于这种特殊情况,额外的事务来自不同的服务(用于编写统计数据)。我们感兴趣的服务的交易已暂停

查看线程,它正在等待来自池的连接

我们做了一个小测试来检查事务的传播。该测试并不复制我们的体系结构,但旨在复制问题

@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
@ContextConfiguration(classes = { //
        TransactionTest.class, //
        ClientDataSourceConfig.class, //
        TransactionTest.TestFakeService.class })
@Configurable
public class TransactionTest {

    @Autowired
    DataSource primaryDataSource;
    @Autowired
    PlatformTransactionManager primaryHibernateTransactionManager;
    @Autowired
    EntityManagerFactory primarySessionFactory;
    @Autowired
    TestFakeService fakeService;

    // --------------
    @Test
    public void transactionTest() {
        Tree tree = fakeService.getTree();
        fakeService.getTree2();
        assertNotNull(tree);
    }

    @Component
    @Transactional(readOnly = true)
    public class TestFakeService {

        public Tree getTree() {
            EntityManager em = primarySessionFactory.createEntityManager();
            Tree tree = em.find(Tree.class, "ID");
            fakeService.getTree2();
            return tree;
        }

        public Tree getTree2() {
            EntityManager em = primarySessionFactory.createEntityManager();
            Tree tree = em.find(Tree.class, "ID");
            return tree;
        }
    }
}
这导致了以下跟踪(没有来自测试初始化的日志。我使用了pastebin,因为我达到了字符限制)

我们从测试中注意到: *我们调用第一个方法->创建事务 *第二个方法从调用事务->创建新事务(而不是传播现有事务)开始调用 *再次获取实体(而不是使用Hibernate会话中的实体)

2)配置

以下是数据源的配置:

@Configuration
@PropertySource({ "classpath:datasources.properties" })
@EnableTransactionManagement
public class ClientDataSourceConfig {

    @Autowired
    private Environment env;

    /**************** DATASOURCE CONFIG *****************/

    @Value("${jdbc.client.db}")
    private String dataDatabase;
    @Value("${jdbc.client.host}")
    private String host;
    @Value("${jdbc.client.port}")
    private String port;
    @Value("${jdbc.client.driver.class}")
    private String driverClassName; // org.mariadb.jdbc.Driver
    @Value("${jdbc.client.driver.name}")
    private String driverName; // mariadb
    @Value("${jdbc.client.user}")
    private String username;
    @Value("${jdbc.client.pass}")
    private String password;

    /*************** HIBERNATE CONFIG ******************/

    @Value("${hibernate.dialect}")
    private String hibernateDialect; // org.hibernate.dialect.MySQLDialect
    @Value("${hibernate.show_sql}")
    private String hibernateShowSql;
    @Value("${hibernate.current_session_context_class}")
    private String sessionContextClass; //org.springframework.orm.hibernate5.SpringSessionContext

    /*************************************/

    @Bean(name = "clientEntityManager")
    @Primary
    public EntityManagerFactory clientEntityManager(
            @Qualifier("clientDataSource") DataSource clientDataSource) {

        HibernateJpaVendorAdapter hibernateVendorAdapter = new HibernateJpaVendorAdapter();

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();

        em.setJpaVendorAdapter(hibernateVendorAdapter);

        em.setDataSource(clientDataSource);
        em.setMappingResources("HibernateQueries.xml");
        em.setPackagesToScan(new String[] { //
                "entity.package", //
        });

        Properties properties = new Properties();
        properties.put("hibernate.dialect", hibernateDialect);
        properties.put("hibernate.show_sql", hibernateShowSql);
        properties.put("hibernate.current_session_context_class", sessionContextClass);
        em.setJpaProperties(properties);
        em.afterPropertiesSet();

        return em.getObject();
    }

    @Bean(name = "clientDataSource")
    @Primary
    public DataSource getDataSource() throws SQLException {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(driverClassName);
        ds.setUrl("jdbc:" + driverName + "://" + host + ":" + port + "/" + dataDatabase);
        ds.setUsername(username);
        ds.setPassword(password);

        return ds;
    }

    @Bean(name = "clientDataSourceTx")
    @Primary
    public PlatformTransactionManager clientDataSourceTx(
            @Qualifier("clientEntityManager") EntityManagerFactory entityManagerFactory) {

        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);

        return transactionManager;
    }
}
3)问题

总之,我们不明白为什么当我们直接使用hibernate的会话时,这种配置能够完美地工作,而在使用JPA的EntityManagerFactory时却不能

为什么到数据库的活动连接数量不断增加,而没有看到任何类型的日志显示连接池,为什么在我们设计服务/DAO层时创建了如此多的事务,以确保服务的方法不会被调用