У меня возникла проблема с транзакциями в моем приложении. Я использую Java 1.6 и Hibernate 3.2.5.
Мое приложение запускает ежемесячный процесс, в котором создаются записи для каждого пользователя в базе данных на основе их ежемесячной активности. Эти платежные записи затем используются для создания объекта Ежемесячный счет. Процесс такой:
- Получить пользователей, которые имели активность в прошлом месяце
- Создание соответствующих платежных записей для каждого пользователя
- Получите набор платежных записей, которые мы только что создали
- Создание ежемесячного счета на основе этих записей
Все отлично работает до шага 3 выше. Записи для выставления счета созданы правильно (я вижу их в базе данных, если добавляю точку останова после метода создания записи для выставления счета), но они не извлекаются из базы данных. В результате создается неправильный ежемесячный счет.
Если я снова запускаю код (без очистки базы данных), создаются новые платежные записи, и на шаге 3 извлекаются записи, созданные в первом запуске (но не во втором запуске). Это очень сбивает с толку.
Мой код выглядит следующим образом:
for (User user : usersWithActivities) {
createBillingEntriesForUser(user.getId());
userBillingEntries = getLastMonthsBillingEntriesForUser(user.getId());
createXMLBillForUser(user.getId(), userBillingEntries);
}
Вызванные методы выглядят следующим образом:
@Transactional
public void createBillingEntriesForUser(Long id) {
UserManager userManager = ManagerFactory.getUserManager();
User user = userManager.getUser(id);
List<AccountEvent> events = getLastMonthsAccountEventsForUser(id);
BillingEntry entry = new BillingEntry();
if (null != events) {
for (AccountEvent event : events) {
if (event.getEventType().equals(EventType.ENABLE)) {
Calendar cal = Calendar.getInstance();
Date eventDate = event.getTimestamp();
cal.setTime(eventDate);
double startDate = cal.get(Calendar.DATE);
double numOfDaysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
double numberOfDaysInUse = numOfDaysInMonth - startDate;
double fractionToCharge = numberOfDaysInUse/numOfDaysInMonth;
BigDecimal amount = BigDecimal.valueOf(fractionToCharge * Prices.MONTHLY_COST);
amount.scale();
entry.setAmount(amount);
entry.setUser(user);
entry.setTimestamp(eventDate);
userManager.saveOrUpdate(entry);
}
}
}
}
@Transactional
public Collection<BillingEntry> getLastMonthsBillingEntriesForUser(Long id) {
if (log.isDebugEnabled())
log.debug("Getting all the billing entries for last month for user with ID " + id);
//String queryString = "select billingEntry from BillingEntry as billingEntry where billingEntry>=:firstOfLastMonth and billingEntry.timestamp<:firstOfCurrentMonth and billingEntry.user=:user";
String queryString = "select be from BillingEntry as be join be.user as user where user.id=:id and be.timestamp>=:firstOfLastMonth and be.timestamp<:firstOfCurrentMonth";
//This parameter will be the start of the last month ie. start of billing cycle
SearchParameter firstOfLastMonth = new SearchParameter();
firstOfLastMonth.setTemporalType(TemporalType.DATE);
//this parameter holds the start of the CURRENT month - ie. end of billing cycle
SearchParameter firstOfCurrentMonth = new SearchParameter();
firstOfCurrentMonth.setTemporalType(TemporalType.DATE);
Query query = super.entityManager.createQuery(queryString);
query.setParameter("firstOfCurrentMonth", getFirstOfCurrentMonth());
query.setParameter("firstOfLastMonth", getFirstOfLastMonth());
query.setParameter("id", id);
List<BillingEntry> entries = query.getResultList();
return entries;
}
public MonthlyBill createXMLBillForUser(Long id, Collection<BillingEntry> billingEntries) {
BillingHistoryManager manager = ManagerFactory.getBillingHistoryManager();
UserManager userManager = ManagerFactory.getUserManager();
MonthlyBill mb = new MonthlyBill();
User user = userManager.getUser(id);
mb.setUser(user);
mb.setTimestamp(new Date());
Set<BillingEntry> entries = new HashSet<BillingEntry>();
entries.addAll(billingEntries);
String xml = createXmlForMonthlyBill(user, entries);
mb.setXmlBill(xml);
mb.setBillingEntries(entries);
MonthlyBill bill = (MonthlyBill) manager.saveOrUpdate(mb);
return bill;
}
Помощь с этим вопросом будет принята с благодарностью, так как она уже несколько недель мучает меня!
Заранее спасибо,
Gearoid.