来自厄瓜多尔的问候:使用Hibernate +春季3个事务数据库
目前我已经创建了我必须在3名不同的数据库进行操作的项目。为此,我决定使用Hibernate ORM 5.2.7,Spring Framework 4.3.6和其他库来实现连接池等。春天的上下文的配置的实施支持我的注解,我在下面显示:
@Configuration
@ComponentScan("fttg.*")
@EnableTransactionManagement
@EnableScheduling
@PropertySources({
@PropertySource("classpath:application.properties"),
@PropertySource("classpath:schedule.properties")
})
public class ApplicationConfig {
@Autowired
private Environment environment;
@Bean(destroyMethod = "close")
public BasicDataSource dataSourceBitacora() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver"));
dataSource.setUrl(environment.getRequiredProperty("bitacora.jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("bitacora.jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("bitacora.jdbc.password"));
dataSource.setPoolPreparedStatements(true);
dataSource.setInitialSize(4);
dataSource.setMaxTotal(4);
dataSource.setMaxIdle(2);
dataSource.setMinIdle(1);
dataSource.setDefaultAutoCommit(Boolean.FALSE);
return dataSource;
}
@Bean(destroyMethod = "close")
public BasicDataSource dataSourceFacturacion() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver"));
dataSource.setUrl(environment.getRequiredProperty("facturacion.jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("facturacion.jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("facturacion.jdbc.password"));
dataSource.setPoolPreparedStatements(true);
dataSource.setInitialSize(1);
dataSource.setMaxTotal(4);
dataSource.setDefaultAutoCommit(Boolean.FALSE);
return dataSource;
}
@Bean(destroyMethod = "close")
public BasicDataSource dataSourceSietab() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver"));
dataSource.setUrl(environment.getRequiredProperty("sietab.jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("sietab.jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("sietab.jdbc.password"));
dataSource.setPoolPreparedStatements(true);
dataSource.setInitialSize(1);
dataSource.setMaxTotal(2);
dataSource.setDefaultAutoCommit(Boolean.FALSE);
return dataSource;
}
@Bean
public LocalSessionFactoryBean sessionFactoryBitacora() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSourceBitacora());
sessionFactory.setPackagesToScan(environment.getRequiredProperty("bitacora.sessionFactory.packagesToScan"));
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
sessionFactory.setHibernateProperties(properties);
return sessionFactory;
}
@Bean
public LocalSessionFactoryBean sessionFactoryFacturacion() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSourceFacturacion());
sessionFactory.setPackagesToScan(environment.getRequiredProperty("facturacion.sessionFactory.packagesToScan"));
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
sessionFactory.setHibernateProperties(properties);
return sessionFactory;
}
@Bean
public LocalSessionFactoryBean sessionFactorySietab() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSourceSietab());
sessionFactory.setPackagesToScan(environment.getRequiredProperty("sietab.sessionFactory.packagesToScan"));
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
sessionFactory.setHibernateProperties(properties);
return sessionFactory;
}
@Bean
public HibernateTransactionManager transactionManagerBitacora() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactoryBitacora().getObject());
return txManager;
}
@Bean
public HibernateTransactionManager transactionManagerFacturacion() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactoryFacturacion().getObject());
return txManager;
}
@Bean
public HibernateTransactionManager transactionManagerSietab() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactorySietab().getObject());
return txManager;
}
}
的DAOS配置是数据库中的所有对象都相同:
@Repository
public class BitacoraFacturasDetalleDao extends GenericDaoImpl<BitacoraFacturasDetalle, Integer>{
private final static Logger LOGGER = Logger.getLogger(BitacoraFacturasDetalleDao.class);
@Qualifier("sessionFactoryBitacora")
@Autowired
private SessionFactory sessionFactory;
public BitacoraFacturasDetalleDao() {
super(BitacoraFacturasDetalle.class);
}
public BitacoraFacturasDetalle findByEstablecimientoAndPuntoEmisionAndSecuencial(String establecimiento, String puntoEmision, String secuencial) {
LOGGER.info("evento findByEstablecimientoAndPuntoEmisionAndSecuencial");
BitacoraFacturasDetalle ret = (BitacoraFacturasDetalle) getCurrentSession().createNamedQuery("BitacoraFacturasDetalle.findByEstablecimientoAndPuntoEmisionAndSecuencial").setParameter("establecimiento", establecimiento).setParameter("puntoEmision", puntoEmision).setParameter("secuencial", secuencial).uniqueResult();
return ret;
}
@Override
protected Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
交易对象实现如下:
@Service("facturasService")
@Transactional(value="transactionManagerFacturacion", readOnly = false)
public class FacturasServiceImpl implements FacturasService, Serializable {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(FacturasServiceImpl.class);
@Autowired
private FacturasCabeceraDao facturasCabeceraDao;
@Override
public boolean save(FacturasCabecera factura) {
LOGGER.info("evento save");
return facturasCabeceraDao.save(factura);
}
}
@Service("bitacoraFacturasDetalleService")
@Transactional(readOnly = false, value = "transactionManagerBitacora")
public class BitacoraFacturasDetalleServiceImpl implements BitacoraFacturasDetalleService, Serializable {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(BitacoraFacturasDetalleServiceImpl.class);
@Autowired
private BitacoraFacturasDetalleDao bitacoraFacturasDetalleDao;
@Override
public boolean save(BitacoraFacturasDetalle b) {
LOGGER.info("evento save");
return bitacoraFacturasDetalleDao.save(b);
}
@Override
public boolean edit(BitacoraFacturasDetalle b) {
LOGGER.info("evento edit");
return bitacoraFacturasDetalleDao.edit(b);
}
@Override
@Transactional(readOnly = true, value = "transactionManagerBitacora")
public BitacoraFacturasDetalle findByEstablecimientoAndPuntoEmisionAndSecuencial(String establecimiento, String puntoEmision, String secuencial) {
LOGGER.info("evento findByEstablecimientoAndPuntoEmisionAndSecuencial");
return bitacoraFacturasDetalleDao.findByEstablecimientoAndPuntoEmisionAndSecuencial(establecimiento, puntoEmision, secuencial);
}
}
而且在实现石英服务我调用通过3种不同类型的服务: 我从数据库中检索信息,生成几个xmls,在第二个数据库中插入bitacora的记录,如果此操作正确,我更新从第一个基础检索到的记录状态,然后在其上创建数字签名生成的xmls如果这个动作正确执行,我在第二个数据库的记录中进行状态更改,并插入两个表类型第三个数据库的主和细节
然后我用这个代码调用:
@Service
public class ScheduleService implements Serializable {
@Autowired
private LocalidadService localidadService;
@Autowired
private CooperativaService cooperativaService;
@Autowired
private BoletoTasaService boletoTasaService;
@Autowired
private BitacoraFacturasDetalleService bitacoraFacturasDetalleService;
@Autowired
private InformacionTributariaService informacionTributariaService;
@Autowired
private ClientesService clientesService;
@Autowired
private FacturasService facturasService;
@Scheduled(cron = "${schedule.cronExpresion}")
public void start() {
if(XMLUtil.generarXML(factura, XML_GENERADO)) {
LOGGER.info("XML para la factura " + SECUENCIAL_DOCUMENTO + " generado correctamente");
//code that fills a javaBean
//Execution of service that inserts in the database # 2
if(bitacoraFacturasDetalleService.save(bitacoraFacturaDetalle)) {
LOGGER.info("Factura " + SECUENCIAL_DOCUMENTO + " registrada en bitacora correctamente");
// object retrieved from database # 1 to be changed status not to be taken into account in future
tasa.setStatusFacturacionElectronica("P");
if(boletoTasaService.update(tasa)) {
//Other post-upgrade operations
}
}
}
}
这种情况是,这段代码一直工作到一定数量的寄存器(大约700或800的数据库1),在下一个插入或更新diff erent基地代码进入“休眠”状态,在很多时间后再次运行
对于转换到生产之前执行的测试,请复制3个数据库,这些数据库对于此场景而言没有并发连接与他们交互的系统和/或界面。
我不知道“问题”的原因是:使用的编程代码,定义事务对象的策略(我已阅读并被建议使用JTA,但从我已阅读的机制中仅使用该机制事务性线程[控制数据库上的操作的服务]),或者如果由于其他应用程序与不同数据库的表的配合而带来此不便
如果弹簧配置有任何问题,请帮忙,交易服务的定义,或者如果您肯定需要为此使用JTA。
有可能表明我曾经使用过这种方案,我有一个或几个数据库,从中我可以提取信息,只有一个数据库可以插入,因此我没有问题;另一方面,在给定的情况下写入三个数据库
我在想第三个数据库只使用spring,第二个只使用hibernate,而第一个只使用jdbc。你怎么看? –
我不明白这一点。试着找出数据库为什么卡住了。它必须等待某个锁定,或者等待VACUUM过程。 –