Background: I am using Hibernate in DAOs, which are used by a business layer class. Everything is autowired in Spring. I wire the sessionManager into the DAO, then wire the DAO into the business logic class.
I am doing annotation-based transaction management using @Transactional.
The error that I am seeing is as follows:
Could not create JDBC savepoint;
nested exception is
java.sql.SQLException: Connection is read-only.
Queries leading to data modification are not allowed.
The method at which the exception is thrown is a read-only method, containing two read-only reads, in sequence.
I've tried to distill the code as much as possible into this demo:
@Transactional(propagation = Propagation.REQUIRES_NEW,value="transactionManager",readOnly=true)
public Typ2 validateAndIfSoGet(String param){
Typ blah = dao1.getTyp(param);
if(blah!=null){
return dao2.getTyp2(blah);
}
else return null;
}
You can see that there are two reads happening from different DAO objects in this one transaction. Why is Spring complaining about a save point? Must there be some save between the reads? Would the correct fix then be to make it readOnly=false? Or would that be a band-aid cover up fix?
Thanks in advance.
Edit:
getTyp()
and getType2()
are DAO methods that make calls to the respective underlying databases to retrieve rows as objects. They use simple Hibernate mappings (1 DAO: 1 table, 1 row: 1 entity object.)
The full getTyp method looks like this:
@Override
@Transactional(value="transactionManager",propagation = Propagation.NESTED,readOnly=true)
public Typ getTyp(String param){
Typ typ = (Typ) currentSession().get(Typ.class, param);
return typ;
}
(using Hibernate's Session.get method).
The getCurrentSession method is not annotated. I'm not sure if this has anything to do with the problem.
@Autowired
@Qualifier("sessionFactory")
private SessionFactory sessFactory;
private Session currentSession(){
return sessFactory.getCurrentSession();
}