Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Not A Bug
-
Affects Version/s: 1.3.7
-
Fix Version/s: None
-
Component/s: Persistence, Services
-
Labels:None
-
Environment:Windows 7 64Bit, OpenSuse 11.1, Postgres 8.4
-
Testcase included:yes
Description
I'm trying to invoke .save(flush:true) from within a readOnly transaction.
When using HSQLDB I was able to have:
@Transactional(readOnly=true) def someMethod(String name) { def test = new TestDomainObject(name: name) test.save(flush:true) }
and it would work fine. Everything else in this transaction would be rolled back but testDomainObject would be saved.
Unfortunately after changing the database to Postgres this code stopped working. I think it still should, however I understand that it might only be my wish.
So I have tried to solve it using:
@Transactional(readOnly=true) def testSomething(String name) { testSomethingRW(name) } @Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW) def testSomethingRW(String name) { def test = new Test(name: name) test.save(flush: true) }
Unfortunately this doesn't work either. I'm getting Transaction read only errors coming from Postgres.
I thought this code would allow me to create a new read/write transaction, save the object and commit transaction.
I have attached the project I used for testing. Please note, this WILL work with HSQLDB, but it does not with Postgres.
to try it just run the app and use:
http://localhost:8080/test/testSomething?name=blah
-
Hide
- TransactionalTests.zip
- 18/Dec/11 1:18 PM
- 824 kB
- Krystian Szczesny
-
- TransactionalTests/.classpath 0.7 kB
- TransactionalTests/.project 0.5 kB
- TransactionalTests/application.properties 0.2 kB
- TransactionalTests/.../BootStrap.groovy 0.1 kB
- TransactionalTests/.../BuildConfig.groovy 1 kB
- TransactionalTests/.../Config.groovy 4 kB
- TransactionalTests/.../DataSource.groovy 1 kB
- TransactionalTests/.../resources.groovy 0.0 kB
- TransactionalTests/.../UrlMappings.groovy 0.2 kB
- TransactionalTests/.../TestController.groovy 0.2 kB
- TransactionalTests/.../Test.groovy 0.1 kB
- TransactionalTests/.../messages.properties 3 kB
- TransactionalTests/.../messages_da.properties 3 kB
- TransactionalTests/.../messages_de.properties 4 kB
- TransactionalTests/.../messages_es.properties 3 kB
- TransactionalTests/.../messages_fr.properties 2 kB
- TransactionalTests/.../messages_it.properties 2 kB
- TransactionalTests/.../messages_ja.properties 2 kB
- TransactionalTests/.../messages_nl.properties 3 kB
- TransactionalTests/.../messages_pt_BR.properties 3 kB
- TransactionalTests/.../messages_pt_PT.properties 3 kB
- TransactionalTests/.../messages_ru.properties 4 kB
- TransactionalTests/.../messages_th.properties 5 kB
- TransactionalTests/.../messages_zh_CN.properties 2 kB
- TransactionalTests/.../TestService.groovy 0.5 kB
- TransactionalTests/grails-app/.../error.gsp 2 kB
- TransactionalTests/grails-app/.../index.gsp 4 kB
- TransactionalTests/grails-app/.../main.gsp 0.8 kB
- TransactionalTests/.../postgresql-8.4-702.jdbc4.jar 527 kB
- TransactionalTests/.../application.properties 0.2 kB
Activity
- All
- Comments
- Work Log
- History
- Activity
- Git Commits
My current scenario is:
User object has custom setters, which based on time, change some values.
But this user can list other users, so after loading User object which represents user calling my API I am loading a collection of other objects of User class. Their setters CAN change some values as well, but I don't want to store these changes in the database [because I don't want to have it stored and because it can cause stale object exceptions in other transactions]. To prevent this situation I am creating readonly transactions where I do some heavy lifting and then only explicitly save the data I want to save. This is just an example.
ok, consider a different scenario:
You create a new object in controller and update it in service + you update existing object in service.
public class Test { String name }
Controller action
def testOne = {
def test = new Test()
testService.something(test, params.name)
test.save(flush:true)
}
Service method
@Transactional(readOnly=true, propagate=Propagation.REQUIRES_NEW) def something(Test a, String name) { a.name = name Test.get(1).name = "just a test" }
New object will be saved and old object will be updated.
Ok.. I have found the solution [ http://stackoverflow.com/questions/8569090/spring-hibernate-postgresql-readonly-transaction-save-on-demand ]. In order to make it work I had to add
def testService
and call the method
testService.testSomethingRW(name)
phew... ![]()
Issue can be closed.
I don't understand, why would you try a write operation in a read-only transaction?