-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: What are the dangers of long-term production use of this?
PostPosted: Thu Sep 24, 2009 7:48 am 
Regular
Regular

Joined: Tue May 12, 2009 6:08 am
Posts: 92
I wrote a custom constraint which allows me to do queries against hibernate. This is helpful to detecting duplicates in the database and that sort of thing, and doing it declaratively and quickly.

Here is an example:
Code:
@QueryConstraint(
   hql = "select count(*) from UserAccount where emailAddress = :emailAddress and id != :id",
   message = "{userAccount.email.unique}" )


The idea is that if the query returns 0, then all is well... and if the query returns 1 or more results, then there is a validation problem.

Now, conceptually this is really nice (for me anyway). I am a little worried about the long-term use of this constraint. Will it cause problems with sessions? Will not going through spring's transaction layer create problems?

My validator looks like this:
Code:
public class QueryConstraintValidator implements ConstraintValidator<QueryConstraint,DomainObject> {

   private String hql;

   public void initialize( QueryConstraint queryConstraint ) {
      this.hql = queryConstraint.hql();
   }

   public boolean isValid( DomainObject domainObject, ConstraintValidatorContext context ) {
      BeanWrapper beanWrapper = new BeanWrapperImpl( domainObject );

      SessionFactory sessionFactory =
         ( SessionFactory ) ApplicationContextProvider.getBean( "sessionFactory" );

      if( sessionFactory != null ) {
         StatelessSession statelessSession = sessionFactory.openStatelessSession();
         Query query = statelessSession.createQuery(
            HqlParser.removePeriodsFromParameterNames( hql )
         );

         for( String parameterName : HqlParser.getParameterNames( hql ) ) {
            query.setParameter(
               HqlParser.removePeriodsFromParameterName( parameterName ),
               beanWrapper.getPropertyValue( parameterName )
            );
         }

         boolean result = (Long) query.uniqueResult() == 0;

         statelessSession.close();

         return result;
      }

      return true;
   }


I get a stateless session, because that works and I guess it has low risk associated with it. I be sure to close it once I'm done making the query.

Try and disregard all that stuff about HqlParser.*... that's just parsing the query so we can get the property values to use as parameters. I have to fix up the names a bit since doing stuff like "myObject.property = :myObject.property" will cause hibernate to bomb if that is used as a parameter name. Hibernate really just wants "myObject.property = :myObjectProperty" - and that works just fine. That's really all HqlParser is doing here... as well as parsing the string for all the property names in a nice convenient list.

So are there any dangers to what I am doing? Or is this safe?


Top
 Profile  
 
 Post subject: Re: What are the dangers of long-term production use of this?
PostPosted: Fri Sep 25, 2009 7:00 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I think this is a valid approach. I guess you could also use the current session in this case though.
From a design point of view it is a little bit of a shame that you have to explicitly use ApplicationContextProvider to get to your bean. At this stage you start using spring class where you don't want to have them.

An alternative approach to this is to write a custom ConstraintValidatorFactory. The default factory used used the no-arg constructor to instantiate constraint validator. Using a custom factory you can use any mechanism you like to instantiate your constraint validators including IOC via spring. You only have to implement a single method - getInstance(Class<T> key)

To use the custom factory you can build your ValidatorFactory via
Code:
Validation.byDefaultProvider().configure().constraintValidatorFactory(new MyIOCFactory()).buildValidatorFactory()


This way you place the IOC stuff where it belongs.

--Hardy


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.