Propagation.REQUIRES_NEW may be problematic due to locking.

If we go down the path of having Propagation.SUPPORTS or even not declaring
@Transactional at all on read only methods, it'll be even easier to support
your use case Burke. You'll just start a transaction if you need it. It'll
mean that reads will be non-transactional by default which should give us
improved performance as well. There's no reason why simple reads should be
transactional anyway.

Ben, I haven't tested it yet on our configuration of spring/hibernate, but
I'll do it soon and let you know.

-Rafal


On 27 February 2012 23:07, Burke Mamlin <[email protected]> wrote:

> Yeah.  That's what I was hoping for – i.e., that we figure out the best
> practice (at least based on what we know now) and promote/document it so
> people don't have to figure this out on their own.
>
> -Burke
>
>
> On Mon, Feb 27, 2012 at 4:53 PM, Darius Jazayeri 
> <[email protected]>wrote:
>
>> You can annotate a method with @Transactional(propagation=REQUIRES_NEW).
>> I don't know whether this is supported on all databases, or whether there
>> are any other pitfalls in practice.
>>
>> -Darius
>>
>>
>> On Mon, Feb 27, 2012 at 8:45 AM, Burke Mamlin <[email protected]>wrote:
>>
>>> Can we devise a convention/recipe for cleanly creating a separate
>>> writable transaction within a read-only transaction?  If someone
>>> wants/needs to create some side effects inside a read-only transaction, it
>>> would be nice to have a common convention for how to implement such a side
>>> effect (e.g., either appropriate annotations and/or a utility method).
>>>
>>> For example, a service provides a transactionless or read-only
>>> transaction around a method and some process introduced by a module during
>>> that method wants to write something to the database on the side.  Is there
>>> a way for the module to create it's own separate transaction to perform the
>>> side effect without forcing the service method to create a transaction?
>>>
>>> -Burke
>>>
>>>
>>> On Mon, Feb 27, 2012 at 9:59 AM, Ben Wolfe <[email protected]> wrote:
>>>
>>>> @Transactional(readOnly=true, propagation=Propagation.SUPPORTS) looks
>>>> like the best solution.
>>>>
>>>> Dissecting that suggestion according to the article:
>>>>
>>>> *@Transactional* so that hibernate is happen and has its endpoints
>>>> *readOnly=true* so that a database write doesn't occur
>>>> *Propogation.SUPPORTS* so that the transaction is never really started
>>>> unless asked for
>>>>
>>>> Did you confirm this still works with hibernate? (validating my first
>>>> assumption above about @Transactional?)
>>>>
>>>> All read/write methods will need
>>>> @Transaction(propogration=Propogration.REQUIRED)
>>>>
>>>> Ben
>>>>
>>>>
>>>> On Sun, Feb 26, 2012 at 7:22 AM, Rafal Korytkowski 
>>>> <[email protected]>wrote:
>>>>
>>>>> I'd vote to put @Transactional(readOnly=true,
>>>>> propagation=Propagation.SUPPORTS) at the class level of service layer 
>>>>> impls
>>>>> and fine tune methods that aren't read only.
>>>>>
>>>>> Propagation.SUPPORTS allows to eliminate the transaction overhead that
>>>>> Darius is hoping to achieve with the DAO example in a more general and
>>>>> nicer way. More info here [0].
>>>>>
>>>>> There's not much difference between having transactional DAOs and
>>>>> Services. The latter is more widely used for the reason I gave, but it's a
>>>>> matter of taste.
>>>>>
>>>>> -Rafal
>>>>>
>>>>> [0] - http://www.ibm.com/developerworks/java/library/j-ts1/index.html
>>>>>
>>>>>
>>>>> On 24 February 2012 22:00, Darius Jazayeri <[email protected]>wrote:
>>>>>
>>>>>> Spring tries to use the existing transaction unless you say
>>>>>> @Transactional(propagation=Propagation.REQUIRES_NEW).
>>>>>>
>>>>>> I would *love* to get rid of the @Transactional annotations on our
>>>>>> services, and just put annotations on the methods that actually require
>>>>>> them.
>>>>>>
>>>>>> -Darius
>>>>>>
>>>>>>
>>>>>> On Fri, Feb 24, 2012 at 12:32 PM, Ben Wolfe <[email protected]> wrote:
>>>>>>
>>>>>>> FYI, here is the relevant ticket:
>>>>>>> https://tickets.openmrs.org/browse/TRUNK-208
>>>>>>>
>>>>>>> I could live with it on the DAO if we also examine all serviceimpls
>>>>>>> for multiple calls to the DAO layer and add the annotation to the impl 
>>>>>>> if
>>>>>>> it does more than one.
>>>>>>>
>>>>>>> Can we do away with the generic @Transactional on the class and
>>>>>>> force devs to add @Transactional on methods that need it?  This should
>>>>>>> remove the need for @Transactional(readOnly=true) and limit the number 
>>>>>>> of
>>>>>>> times its forgotten.  Alternatively, we make the class level annotation
>>>>>>> readOnly=true.
>>>>>>>
>>>>>>> Are we also sure that if a transaction is started at the service
>>>>>>> layer that the DAO layer is using that same one instead of starting a 
>>>>>>> new
>>>>>>> one?
>>>>>>>
>>>>>>> Ben
>>>>>>>
>>>>>>>
>>>>>>> On Fri, Feb 24, 2012 at 3:13 PM, Darius Jazayeri <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> The reason I'd rather have them in the HibernateDAO is so we can
>>>>>>>> write a service method like this, without paying the transactional 
>>>>>>>> penalty:
>>>>>>>>
>>>>>>>> public MySettings getSettings() {
>>>>>>>>     if (cached == null) {
>>>>>>>>         cached = dao.getSettings(); // this method has an
>>>>>>>> @Transactional annotation
>>>>>>>>     }
>>>>>>>>     return cached;
>>>>>>>> }
>>>>>>>>
>>>>>>>> Basically I'm saying that the transactional annotation should be
>>>>>>>> put in the concrete DAO only where we actually hit a transactional
>>>>>>>> datastore.
>>>>>>>>
>>>>>>>> If we're putting the annotations in the ServiceImpl I'd need to do
>>>>>>>> something like this:
>>>>>>>>
>>>>>>>> public MySettings getSettings() {
>>>>>>>>     if (cached == null) {
>>>>>>>>         cached = getSettingsFromDao();
>>>>>>>>     }
>>>>>>>>     return cached;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Transactional(readOnly=true)
>>>>>>>> private MySettings getSettingsFromDao() {
>>>>>>>>     return dao.getSettings();
>>>>>>>> }
>>>>>>>>
>>>>>>>> It's not the end of the world to have to do that, but is there any
>>>>>>>> theoretical justification or best-practice recommendation that says we
>>>>>>>> should put annotations in the service layer when we believe that we're
>>>>>>>> calling a transactional DAO, rather than in the DAO layer when we know 
>>>>>>>> for
>>>>>>>> sure we're hitting the datastore?
>>>>>>>>
>>>>>>>> -Darius
>>>>>>>>
>>>>>>>> PS- Definitely if a ServiceImpl or a Controller method is going to
>>>>>>>> make multiple Service or DAO calls, it should explicitly mark the
>>>>>>>> transaction itself. But that's independent.
>>>>>>>>
>>>>>>>>
>>>>>>>> On Fri, Feb 24, 2012 at 10:08 AM, Ben Wolfe <[email protected]>wrote:
>>>>>>>>
>>>>>>>>> Yes, lets move these to the ServiceImpl.  Do we have a ticket
>>>>>>>>> somewhere to move the rest of our transaction annotations from 
>>>>>>>>> interface to
>>>>>>>>> impl?
>>>>>>>>>
>>>>>>>>> Ben
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Fri, Feb 24, 2012 at 9:55 AM, Wyclif Luyima <[email protected]
>>>>>>>>> > wrote:
>>>>>>>>>
>>>>>>>>>> @Rafal, i agree with what you are saying, so we should move them
>>>>>>>>>> from HibernateVisitDao to VisitServiceImpl?
>>>>>>>>>>
>>>>>>>>>> Wyclif
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Fri, Feb 24, 2012 at 5:15 AM, Rafal Korytkowski <
>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>
>>>>>>>>>>> I've found a way to have the advice around @Transactional so we
>>>>>>>>>>> don't need to change anything in Visits.
>>>>>>>>>>>
>>>>>>>>>>> Anyway, I don't think we should move @Transactional to the DAO
>>>>>>>>>>> layer. In general it's the service layer that defines units of work 
>>>>>>>>>>> that
>>>>>>>>>>> should be transactional. If you have multiple calls to DAO in a 
>>>>>>>>>>> service
>>>>>>>>>>> method, you will want to have @Transactional in the service method 
>>>>>>>>>>> anyway.
>>>>>>>>>>>
>>>>>>>>>>> -Rafal
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 24 February 2012 03:11, Darius Jazayeri 
>>>>>>>>>>> <[email protected]>wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Moving this to the dev list.
>>>>>>>>>>>>
>>>>>>>>>>>> Wyclif, I assume that you mean from HibernateVisitDAO to
>>>>>>>>>>>> VisitServiceImpl...
>>>>>>>>>>>>
>>>>>>>>>>>> So, in the long run, we need to move the transactional
>>>>>>>>>>>> annotations off of the service interface. I'd argue that they 
>>>>>>>>>>>> should go to
>>>>>>>>>>>> the concrete DAO, and only on the methods that actually hit the 
>>>>>>>>>>>> database.
>>>>>>>>>>>> The alternative would be to move them to the ServiceImpl.
>>>>>>>>>>>>
>>>>>>>>>>>> That said, I'm fine if we want to move them from
>>>>>>>>>>>> HibernateVisitDAO up to the VisitService *interface* for
>>>>>>>>>>>> consistency, so that we can refactor *all* our services later.
>>>>>>>>>>>> But what's the argument for moving it from the HibernateDAO to the
>>>>>>>>>>>> ServiceImpl?
>>>>>>>>>>>>
>>>>>>>>>>>> Ideally Rafal will quickly figure out how to move the recent
>>>>>>>>>>>> advice code he wrote so it's triggered by any @Transactional method
>>>>>>>>>>>> anywhere, and this will be moot.
>>>>>>>>>>>>
>>>>>>>>>>>> -Darius
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On Thu, Feb 23, 2012 at 5:58 PM, Wyclif Luyima <
>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi guys,
>>>>>>>>>>>>>
>>>>>>>>>>>>> @Daniel, we need to move the @Transanctional annotations from
>>>>>>>>>>>>> HibernateVisitDao to ConceptServiceImpl before cutting the 1.9 RC
>>>>>>>>>>>>>
>>>>>>>>>>>>> Wyclif
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>> ------------------------------
>>>>>>>>>>>> Click here to 
>>>>>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> ------------------------------
>>>>>>>>>>> Click here to 
>>>>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> ------------------------------
>>>>>>>>>> Click here to 
>>>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ------------------------------
>>>>>>>>> Click here to 
>>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>>>
>>>>>>>>
>>>>>>>> ------------------------------
>>>>>>>> Click here to 
>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>>
>>>>>>>
>>>>>>> ------------------------------
>>>>>>> Click here to 
>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>>  OpenMRS Developers' mailing list
>>>>>>>
>>>>>>
>>>>>> ------------------------------
>>>>>> Click here to 
>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>>  OpenMRS Developers' mailing list
>>>>>>
>>>>>
>>>>> ------------------------------
>>>>> Click here to 
>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>>  OpenMRS Developers' mailing list
>>>>>
>>>>
>>>> ------------------------------
>>>> Click here to 
>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from
>>>>  OpenMRS Developers' mailing list
>>>>
>>>
>>> ------------------------------
>>> Click here to 
>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from 
>>> OpenMRS Developers' mailing list
>>>
>>
>> ------------------------------
>> Click here to 
>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from 
>> OpenMRS Developers' mailing list
>>
>
> ------------------------------
> Click here to 
> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from 
> OpenMRS Developers' mailing list
>

_________________________________________

To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to 
[email protected] with "SIGNOFF openmrs-devel-l" in the  body (not 
the subject) of your e-mail.

[mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

Reply via email to