[Contrib: Evaluation System] AARON: Using SQL in eval DAO
Aaron Zeckoski
azeckoski at unicon.net
Thu Aug 11 08:53:46 PDT 2011
Hibernate doesn't really make it possible to identify the
dialect/vendor as far as I can tell. My recommendation would be to
write your query as a join instead of a subselect since most databases
can efficiently compile joins but mysql is bad at compiling subselects
in most cases.
You could also do it as 2 queries (though there are limits to this
option and it will possibly be slower than a system which can compile
the query effectively).
If that won't work, we can do a hack to pull in the sakai vendor via
spring but we can't just add externallogic as a dependency of the dao
as that creates a loop in the dependencies. Pulling in the vendor is a
poor solution so I would only want to do that if there is no other way
(but I think there are other ways).
<bean id="sakaiDatabaseType"
factory-bean="org.sakaiproject.db.api.SqlService"
factory-method="getVendor" />
-AZ
On Thu, Aug 11, 2011 at 10:15 AM, Jim Eng <jimeng at umich.edu> wrote:
> Hi Aaron,
> I am working on consolidated notifications, in which a student gets one
> announcement or reminder a day instead of one message for each eval they can
> take. I have written HQL in the DAO impl to update records to indicate that
> an announcement has been sent. The query works fine in Oracle but it is
> deadly slow in MySQL. I have tried revising the HQL to generate a better
> MySQL query, but it seems that quirks in hibernate and MySQL make this
> unlikely. I have written SQL that performs very well in MySQL (but only
> MySQL).
> It's easy elsewhere in sakai to write custom SQL for specific vendors.
> Hibernate usually takes care of that, but it fails in this case. If we had
> a way in the DAO of identifying the vendor, I could do this:
> if("mysql".equalsIgnoreCase(dialect)) {
> StringBuilder sqlBuffer = new StringBuilder();
> sqlBuffer.append("update EVAL_ASSIGN_USER eau, EVAL_EMAIL_PROCESSING_QUEUE
> epq ");
> if(sendingAvailableEmails) {
> sqlBuffer.append("set eau.AVAILABLE_EMAIL_SENT=:dateSent ");
> } else {
> sqlBuffer.append("set eau.REMINDER_EMAIL_SENT=:dateSent ");
> }
> sqlBuffer.append("where eau.id = epq.EAU_ID and epq.USER_ID=:userId and
> epq.EMAIL_TEMPLATE_ID=:emailTemplateId");
>
> updateQuery = session.createSQLQuery(sqlBuffer.toString());
>
> } else {
> StringBuilder hqlBuffer = new StringBuilder();
> hqlBuffer.append("update EvalAssignUser ");
> if(sendingAvailableEmails) {
> hqlBuffer.append("set availableEmailSent = :dateSent ");
> } else {
> hqlBuffer.append("set reminderEmailSent = :dateSent ");
> }
> hqlBuffer.append("where id in (select eauId from EvalEmailProcessingData
> where emailTemplateId = :emailTemplateId and userId = :userId)");
>
> updateQuery = session.createQuery(hqlBuffer.toString());
> }
>
> Unfortunately, hibernate does not surface that information that I can see.
> I have tried accessing the "hibernate.dialect" property in various ways,
> and I've looked for anything in the hibernate API's that might identify the
> dialect. Haven't found anything.
> So I'd like to ask this. The database vendor is readily accessible from
> sakai's SqlService. Suppose we added this method to EvalExternalLogic:
> public String getDatabaseVendor();
> What would you think about calling an external logic method in the DAO impl?
> Can you see another way to do this, other than just hanging MySQL users out
> to dry?
> Thanks.
> Jim
>
>
>
--
Aaron Zeckoski - Software Architect - http://tinyurl.com/azprofile
More information about the evaluation
mailing list