i am getting exception javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed in return statement, i am using spring JPA.
StringBuilder queryBuilder = new StringBuilder(querystat);
System.out.println("startDate--->" + startDate);
Query query =
getEntityManager().createQuery(queryBuilder.toString());
System.out.println("query.list();--->"
+ query.getResultList().size());
return query.getResultList();
any one have idea on this issue?
Thanks for responses..i have added transactionTemplate in service class its working.below is the working code..
return transactionTemplate
.execute(new TransactionCallback<List<?>>() {
public List<?> doInTransaction(
TransactionStatus status) {
return dao.monthReportQuery(startDate, endDate);
}
});
The public method calling the code needs to be annotated with #Transactional.
Further, the processing of #Transactional needs to be activated. This might or might not be already active. It can be activated using the #EnableTransactionManagement.
The method annotated with #Transactional shall not be called from the same class.
Related
folks,
The method below is part of a transaction using JPA. I'm trying to discover how to add a functionality in this method so when the query within the method throws an exception, all the transaction rolls back.
What could I do in this case? Below is the code:
#Transactional
public void deleteDadosSExecReenvCancelada(Long nuSeqConsecao){
try{
StringBuilder query = new StringBuilder();
query.append(" DELETE FROM sigpc_fnde.s_execucao_financ_gru_reenv where NU_SEQ_EXEC_FINANC_REENV in (SELECT NU_SEQ_EXECUCAO_FINANCEIRA FROM sigpc_fnde.s_exec_financ_reenv where NU_SEQ_CONCESSAO = ?)");
getEntityManager().createNativeQuery(query.toString()).setParameter(1, nuSeqConsecao).executeUpdate() ;
StringBuilder sql = new StringBuilder();
sql.append(" DELETE FROM sigpc_fnde.s_exec_financ_reenv where NU_SEQ_CONCESSAO = ?");
getEntityManager().createNativeQuery(sql.toString()).setParameter(1, nuSeqConsecao).executeUpdate() ;
} catch (Exception e){
e.getCause();
}
}
I would like to know if simply the Annotation #Transactional(rollbackFor=true) guarantees this condition to happen.
#Transactional will detect any unchecked exception thrown in your method and your transaction will be marked as rollback only. I think #Transactional(rollbackFor = Exception.class) is not necessary in your case since all possible exceptions that could be thrown are RuntimeException.
Also, your EntityManager needs to be injected by Spring. If it's not the case, let Spring inject the EntityManager.
An example on how you could let Spring inject the bean:
#RequiredArgsConstructor
class MyService {
...
#PersistenceContext
private final EntityManager entityManager;
...
}
I am using spring data rest and Spring JPA. I am having one method which update one database table.
#Autowired InvoiceClient;
#Override
#Transactional
public String doBilling(String x){
//get date from TableOne
Bill bill = billsRepository.getBill(x);
if(bill.isPaid()){
generateInvoice();
}
bill.setPaymentDate(new Date());
return "SUCCESS";
}
generateInvoice is non Transactional method which calls #Transactional method from other service.
public void generateInvoice(){
invoiceClient.generateInvoice();//this is #Transactional, make changes in TableTwo
}
In case of any exception in generateInvoice method whole transaction is rolled back.
Now I want to add one more method which will have list of bill numbers. I call doBilling method in loop to do billing for all the bills.
#Override
#Transactional(readOnly = false, rollbackFor = {Throwable.class}, propagation = Propagation.REQUIRED)
public String doBillingForAll(List<String> tx){
for(String x: tx){
doBilling(x);
}
}
But now in case of any exceptions in doBilling method, all the setPayment methods are getting rolled back but generateInvoice is persisted.
I want to rollback generateInvoice also. How can I do it?
You don't need to define a rollbackFor = {Throwable.class}.
By default all RuntimeException do a rollback when using #Transactional.
It can be that because you are using and intermediate non #Transactional annotated method, the main Transaction is suspended and a nested one is created.
Try to put #Transactional in your public void generateInvoice() then Propagation.REQUIRED should be applied with rollback of your invoices
I am using jpa with Play 2.2.1 java .I have a method which finds all the the jobseekers
My controller function
#Transactional
public static Result index() {
return ok(views.html.admin.jobseeker.render("Your new application is ready.", Jobseekers.all()));
}
and model method
public static List<Jobseekers> all() {
#SuppressWarnings("unchecked")
List<Jobseekers> el = JPA.em().createQuery("from Jobseekers order by id").getResultList();
return el;
}
But i am getting exception
[RuntimeException: No EntityManager bound to this thread. Try to annotate your action method with #play.db.jpa.Transactional]
I dont know why its giving this error even though I have added #Transactional
Can anybody help me??
Thanks
Correct annotation is #Transactional not #Transaction
I'm developing a java web application that uses spring like application container. Now while I'm was using the transaction support to spring, I noticed that the time processing of the my annotated method is doubled. Try to descibe the method in a better way:
#Service
public class MyServiceImpl implements MyService{
#Autowired
UtilService utilService;
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void loadContracts(File fileToProcess,UtilDTO dto){
List<MyObject> objects = utilService.readSomethings("xxx","yyy")
//I modify Them
//I save or update them
}
}
#Service
public class UtilServiceImpl implements UtilService{
#PersistenceContext
EntityManager entityManager;
public List<MyObject> readSomethings(String p1,String p2){
String queryString = "from MyObject o where o.param1 = :param1 "
+ " and o.param2 = :param2 ";
Query q = entityManager.createQuery(queryString);
q.setParameter("param1", p1);
q.setParameter("param2", p2);
return q.getResultList();
}
}
For example:
The method readSomething is too late while If I remove the annotation its time processing improves.
Why is there this difference?
The performance is likely due to you creating a new transaction and suspending the existing transactions every time that method is invoked.
From the documentation on Propagation.REQUIRES_NEW, emphasis mine:
Create a new transaction, and suspend the current transaction if one exists. Analogous to the EJB transaction attribute of the same name.
Unless you have specific requirements about creating a new transaction for this method, I would recommend letting it fall through to default behavior - that is, Propagation.REQUIRED.
I am trying to implement logging in DB table using Spring AOP. By "logging in table" I mean to write in special log table information about record that was CREATED/UPDATED/DELETED in usual table for domain object.
I wrote some part of the code and all is working good except one thing - when transaction is rolled back then changes in log table still commit successfully. It's strange for me because in my AOP advice the same transaction is using as in my business and DAO layer. (From my AOP advice I called methods of special manager class with Transaction propagation MANDATORY and also I checked transaction name TransactionSynchronizationManager.getCurrentTransactionName() in business layer, dao layer and AOP advice and it is the same).
Does anyone tried to implement similar things in practice? Is it possible to use in AOP advice the same transaction as in the business layer and rollback changes made in AOP advice if some error in business layer occurs?
Thank you in advance for unswers.
EDIT
I want to clarify that problem with rollback occurs only for changes that was made from AOP advice. All changes that is made in DAO layer are rollbacked successfully. I mean that, for example, if some exception is thrown then changes made in DAO layer will be successfully rollbacked, but in log table information will be saved (commited). But I can't understand why it is like that because as I wrote above in AOP advice the same transaction is using.
EDIT 2
I checked with debugger the piece of the code where I am writting to the log table in AOP advice and it seems to me that JdbcTemplate's update method executes outside transaction because changes had been commited to the DB directly after execution of the statement and before transactional method was finished.
EDIT 3
I solved this problem. Actually, that was my stupid fault. I'm using MySQL. After creation of the log table I did't change DB engine and HeidySQL set MyIsam by default. But MyIsam doesn't support transaction so I changed DB engine to InnoDB (as for all other tables) and now all is working perfectly.
Thank you all for help and sorry for disturbing.
If someone is interested, here is simplified example that illustrate my approach.
Consider DAO class that has save method:
#Repository(value="jdbcUserDAO")
#Transactional(propagation=Propagation.SUPPORTS, readOnly=true, rollbackFor=Exception.class)
public class JdbcUserDAO implements UserDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#LoggedOperation(affectedRows = AffectedRows.ONE, loggedEntityClass = User.class, operationName = OperationName.CREATE)
#Transactional(propagation=Propagation.REQUIRED, readOnly=false, rollbackFor=Exception.class)
#Override
public User save(final User user) {
if (user == null || user.getRole() == null) {
throw new IllegalArgumentException("Input User object or nested Role object should not be null");
}
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
PreparedStatement ps = connection.prepareStatement(SQL_INSERT_USER, new String[]{"ID"});
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setString(3, user.getFullName());
ps.setLong(4, user.getRole().getId());
ps.setString(5, user.geteMail());
return ps;
}
}, keyHolder);
user.setId((Long) keyHolder.getKey());
VacationDays vacationDays = user.getVacationDays();
vacationDays.setId(user.getId());
// Create related vacation days record.
vacationDaysDAO.save(vacationDays);
user.setVacationDays(vacationDays);
return user;
}
}
Here is how aspect looks like:
#Component
#Aspect
#Order(2)
public class DBLoggingAspect {
#Autowired
private DBLogManager dbLogManager;
#Around(value = "execution(* com.crediteuropebank.vacationsmanager.server.dao..*.*(..)) " +
"&& #annotation(loggedOperation)", argNames="loggedOperation")
public Object doOperation(final ProceedingJoinPoint joinPoint,
final LoggedOperation loggedOperation) throws Throwable {
Object[] arguments = joinPoint.getArgs();
/*
* This should be called before logging operation.
*/
Object retVal = joinPoint.proceed();
// Execute logging action
dbLogManager.logOperation(arguments,
loggedOperation);
return retVal;
}
}
And here is how my db log manager class LooksLike:
#Component("dbLogManager")
public class DBLogManager {
#Autowired
private JdbcTemplate jdbcTemplate;
#InjectLogger
private Logger logger;
#Transactional(rollbackFor={Exception.class}, propagation=Propagation.MANDATORY, readOnly=false)
public void logOperation(final Object[] inputArguments, final LoggedOperation loggedOperation) {
try {
/*
* Prepare query and array of the arguments
*/
jdbcTemplate.update(insertQuery.toString(),
insertedValues);
} catch (Exception e) {
StringBuilder sb = new StringBuilder();
// Prepare log string
logger.error(sb.toString(), e);
}
}
It could be to do with the order of the advice - you would want your #Transaction related advice to take effect around(or before and after) your logging related advice. If you are using Spring AOP you can probably control it using the order attribute of the advice - give your transaction related advice the highest precedence so that it executes last on the way out.
Nothing to do with AOP, set datasource property autocommit to false like :
<bean id="datasource" ...>
<property name="autoCommit" value="false/>
</bean>
If you are using xml configuration