來自厄瓜多爾的問候:使用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過程。 –