MY STRUCTURE:
我的所有webApp都是使用Java 8在Spring Boot中开发的。
CASE:
在其中一个指定的应用程序(称为 B )中,我调用了 A 的API。
此API打开与SQL Server的连接,用于读取条目并发送到 B 读取条目的值。
我在本地计算机上运行的 A 和 B 以及 A 官方和 B 本地测试
在测试中我没有任何问题,API工作正常。
但是当我把这个API从官方调用到官方时,几秒钟后我在日志中出现了一些错误,我丢失了与数据库的所有连接:
Forwarding to error page from request [/mycontroller/request] due to exception
[org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5ec9a879 has been closed already]
java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5ec9a879 has been closed already
或:
EntityManager is closed
发生此错误后,我只能重新启动Tomcat服务器以恢复与数据库的连接。
这是我的代码,名为API:
@Override
public void apiCalled() {
try {
for(Entity c : entityRepository.findEntity()) {
String ftt = keycloakRestTemplate.getForEntity(URI.create(mux+"/api/apiCalled?num="+c.getNumber()), String.class).getBody();
if(ftt == null) {
continue;
}
FttDto f = new ObjectMapper().readValue(ftt, FttDto.class);
c.setNumberF(f.getNumberF());
c.setDateF(convertDate(f.getDateF()));
commessaRepository.save(c);
}
} catch (RestClientException | IOException e) {
LOG.error("Api Service Get error: {}", e.getMessage());
}
}
API代码:
@PersistenceContext(unitName="persistenceUnitI24")
private EntityManager emI24;
public FttDto findByNumber(String number) {
Session session = emI24.unwrap(Session.class);
FttI24 fttListI24 = (FttI24) session.createQuery("select f from FttRg r join r.idFttI24 f join r.nota n where n.nota like '%"+number+"%'")
.setCacheMode(CacheMode.IGNORE)
.uniqueResult();
if(fttListI24 == null) {
return null;
}
FttDto ftt = new FttDto();
ftt.setNumberF(fttListI24.getNumberF());
ftt.setDateF(fttListI24.getDateF());
return ftt;
}
有什么想法吗?
修改
这是我的DBs连接的server.xml:
<Resource
name="jdbc/schemaA"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
initialSize="2"
maxActive="4"
maxIdle="2"
minIdle="1"
username="user"
password="password"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://sqlServer_ip/schemaA"
testOnBorrow="true"
testWhileIdle="true"
validationQuery="select 1"
validationInterval="300000"/>
<Resource
name="jdbc/schemaB"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
initialSize="4"
maxActive="8"
maxWait="10000"
maxIdle="8"
minIdle="4"
username="userB"
password="passB"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://mysqlserver_ip/schemaB?zeroDateTimeBehavior=convertToNull"
testOnBorrow="true"
testWhileIdle="true"
validationQuery="select 1"
validationInterval="300000" />
在春季添加DataSource配置。
在WebApp上 B :
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean(name = "dataSource")
@ConfigurationProperties(prefix="spring.datasource")
@Primary
public DataSource dataSource() throws NamingException {
if(Arrays.asList(environment.getActiveProfiles()).contains("dev")) {
return new BasicDataSource();
}else {
Context ctxConfig = new InitialContext();
return (DataSource) ctxConfig.lookup("java:comp/env/jdbc/schemaB");
}
}
@Bean
@Primary
public JpaTransactionManager transactionManager() throws NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.MYSQL);
jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(false);
jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLInnoDBDialect");
return jpaVendorAdapter;
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("domain.mydomain");
entityManagerFactoryBean.setPersistenceUnitName("persistenceUnit");
return entityManagerFactoryBean;
}
}
在WebApp上 A :
@Configuration
public class DataSourceI24Config {
@Autowired
private Environment environment;
@Bean(name = "dataSourceI24")
@ConfigurationProperties(prefix = "spring.datasource.i24")
public DataSource dataSourceI24() throws NamingException {
Context ctxConfig = new InitialContext();
return (DataSource) ctxConfig.lookup("java:comp/env/jdbc/schemaA");
}
@Bean(name="transactionManagerI24")
public JpaTransactionManager transactionManagerI24() throws NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryI24().getObject());
return transactionManager;
}
@Bean(name="entityManagerI24")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryI24() throws NamingException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSourceI24());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("appA.i24.domain");
entityManagerFactoryBean.setPersistenceUnitName("persistenceUnitI24");
[...]
return entityManagerFactoryBean;
}
}
答案 0 :(得分:1)
我和h2数据库有同样的问题。解决方案是在多连接模式下使用db(多于一个可能的连接,连接池)。