Guice and JDBC #2

4 11 2011

So a little while ago, I wrote about jdbc and guice.. I’ve been using mybatis since then.. And it just came to me yesterday “with mybatis you can do simple jdbc with guice”. Something similar to Spring JDBC templates.

So heres how (integer select), using annotation approach in something called a mapper class.


@Select(value = "select ${sql}")
public Integer updateCustomerEntrance(@Param("sql") String sql);

Thats it the only stuff you need to ensure are that your select will return an integer, and thats it. Mybatis will manage connection pool, connection etc for you.

It’s probably also possible for you to just return a object.. you’ll need at least 3 methods one for each type of sql, select update and delete.

However this approach are not at all utilizing mybatis’s power and are prone to SQL injection.. But it will do the job, and you can then go ahead an convert your legacy code slowly to use mybatis’s full potential.

Heres howto setup guice using it:

http://code.google.com/p/mybatis/wiki/Guice





JPQL example queries

28 10 2008

Looking for JPQL queries, look no further. I use this as a reference page myself.

Search for Persons which all live in San Fransisco, New York or Frederikssund, traversal over single relation

SELECT p FROM Person WHERE p.city.id IN ("SF","NY", "FS")

Search for Persons with some of these tags(tags is a list of tags), traversal over list relations: Married, Divorced, OverTheHill

SELECT p FROM Person P JOIN p.tags t WHERE t.name IN ("married","divorced", "overthehill")

Above could be slow..
Search with enumerations:

SELECT p FROM Person WHERE p.enum = com.mypackage.enum.value
</code

Copy paste stuff:

public List searchForEvents(City city,
List eventTypeList,
List eventAdmittance,
List categoryTypeList)
{
List events = new ArrayList();
List categories = new ArrayList();
List admittanceTypes = new ArrayList();
if (eventTypeList.size() > 0 || categoryTypeList.size() > 0
|| eventAdmittance.size() > 0) {
for (EventType event : eventTypeList) {
events.add(EventType.class.getCanonicalName() + "."
+ event.name());
}

for (CategoryType categoryType : categoryTypeList) {
categories.add(CategoryType.class.getCanonicalName() + "."
+ categoryType.name());

}
for (EventAdmittanceType admittanceType : eventAdmittance) {
admittanceTypes.add(EventAdmittanceType.class
.getCanonicalName()
+ "." + admittanceType.name());

}

}
String jpql = "select e from Event e WHERE e.city.id='" + city.getId()
+ "'";
// types
List typesList = new ArrayList();

if (events.size() > 0) {
typesList.add("e.eventType IN ( " + buildJPQL(events, ",") + " ) ");
}
if (categories.size() > 0) {
typesList.add(" e.categoryType IN ( " + buildJPQL(categories, ",")
+ " )");
}
if (admittanceTypes.size() > 0) {
typesList.add(" e.eventAdmittanceType IN ( "
+ buildJPQL(admittanceTypes, ",") + " )");
}
if (typesList.size() > 0) {
jpql += " and " + buildJPQL(typesList, "and");
}

return getJpaTemplate().find(jpql);
}

private String buildJPQL(List sqlList, String delimiter) {
String constructedSQL = "";

for (String subSQL : sqlList) {
constructedSQL += subSQL + " " + delimiter;
}

if(sqlList.size()!=0){
constructedSQL = constructedSQL.substring(0, constructedSQL.length()
- delimiter.length());

}

return constructedSQL;
}





Pump your Java with Caching

25 08 2008

So you want caching. First thing to see are if your application are applicable for it. There’s the 80/20 rule saying that you need to be maximum 20% writing on what you intend to cache, if you deviate too much from these numbers caching stuff could actually slow you down. I had some fun with this on my own “production” machine an old p3 500mhz (keep that in mind when you see results).

Im gonna write about my current stack which are Apache Http+Apache Tomcat, JPA / Hibernate + spring & Apache Wicket, this does’nt mean that you cant benefit from the ideas though if you arent using these frameworks, which leads me to what I believe are number one rule with caching:

Non intrusion , cache needs to be applied lightly in a non intrusive way

That way you can easily switch it off, switch strategies etc.

So with my stack you can actually introduce caching in each layer if you want to, i’ll start at Hibernate.

Caching with Hibernate

As I used Hibernate and my application seemed a bit heavy on the database I optimized everything, but Hibernate I thought lets start here. So I did, enabling the query cache and 2nd level cache were actually very simple and few lines of code. But this approach were very intrusive as the application needed to know about the caching mechanism, I went ahead any how. I spent 2 days pondering why it did not work, I kept getting cache misses even though I saw that the queries were added to the cache. Hibernate forum werent being responsive so I thought maybe theres another way. Which leads me to next thing.

btw I just bought Java Persitence with Hibernate http://www.manning.com/bauer2/ to help me digg into the cache with Hibernate.

Caching with Spring modules cache

So the spring guys has an non intrusive way of applying caching. It’s really simple :

ApplicationContext.xml add:

<import resource="classpath:cacheContext.xml" />

cacheContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:ehcache="http://www.springmodules.org/schema/ehcache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd">

  [4]<ehcache:config failQuietly="true"
configLocation="classpath:ehcache.xml"/>

    <bean id="myCacheKeyGenerator" class="zeuzgroup.core.cache.ZeuzCacheKeyGenerator"/>
    <bean id="myCachingListener" class="zeuzgroup.core.cache.ZeuzCachingListener"/>

    <ehcache:methodMapInterceptors
            cachingInterceptorId="cachingInterceptor"
            flushingInterceptorId="flushingInterceptor">

        <ehcache:cacheKeyGenerator refId="myCacheKeyGenerator"/>

        <ehcache:cachingListeners>
            <ehcache:cachingListener refId="myCachingListener"/>
        </ehcache:cachingListeners>

[1]<ehcache:caching cacheName="translationCache"
methodFQN="zeuzgroup.core.localization.ITranslationService.get*"/>

<!--  Flush cache -->
    [2]<ehcache:flushing cacheNames="translationCache" methodFQN="zeuzgroup.core.localization.ITranslationService.put*" when="after"/>
    </ehcache:methodMapInterceptors>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
               [3] <idref bean="translations"/>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>cachingInterceptor</value>
                <value>flushingInterceptor</value>
            </list>
        </property>
    </bean>
</beans>
ehcache.xml
  1. setup target methods to cache
  2. setup which metods that evict cache
  3. point at beans to look in
  4. point at ehcache.xml

As you can notice theres two beans further more defined(myCachinglistener and mycachingkeygenerator), you can just use the default implementation provided. Although you might want to use your own keygenerator if using datetime properties in your objects, if your methods return objects with new stamps your cache will not be hit. In my setup my wicket page went from 12s to display to 4s (having a 2s round trip).

ehcache.xml

<diskStore path="java.io.tmpdir" />
<defaultCache maxElementsInMemory="1000" eternal="false"
 timeToIdleSeconds="0" timeToLiveSeconds="500" overflowToDisk="true"
 diskPersistent="false" diskExpiryThreadIntervalSeconds="500" />
 <cache name="translationCache" maxElementsInMemory="75000"
eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false"
diskPersistent="false"
 diskExpiryThreadIntervalSeconds="3600" />

Above are also pretty straight forward.. Now onto the next part.

Caching with Wicket, or preparation for web cache.

Caching statefull pages? Well you can. But remember that if you do when others look at the page you cache they’ll get the same result. Please remember that you cant cache pages with ajax on (AFAIK).

So this means that if you have a “simple” solution where you have users that can be either authorized or not it’s pretty straight forward. I went ahead and chose all the pages where my users arent logged in to be cachable. I decided to go with ehcache’s web cache namely the simplefiltercache. And to make it visible for the cache when a page could be cachable I added a noop parameter to all my pages called cache it has the value true. The simplest way to work with a cache are using urls, you might be able to do something http codes and cache all that does not sets the cache control header. But that’s stretching it to far for me.

Code:

public abstract class MyPage extends WebPage {
public static final String CACHEABLE = "cache";

private PageParameters myPageParameters;
[1]    public Boolean canCache() {

        if (MySession.class.isInstance(this.getSession())) {
            MySession mySession = (MySession) this.getSession();
            return !mySession.isAuthorized();
        }
        return true;
    }
    public MyPage(PageParameters pageParameters) {
[2]	myPageParameters = pageParameters;
[3]        BookmarkablePageLink creditsLink = new BookmarkablePageLink("credits",
                CreditsPage.class, getPageParameters(getSession().getLocale()));
        add(creditsLink);
}
[4]   protected PageParameters getPageParameters(Locale locale) {
        PageParameters pageParameters = new PageParameters();
        if (canCache() && !pageParameters.containsKey(CACHEABLE)) {
            pageParameters.add(CACHEABLE, "true");
        }
        if (!canCache()) {
            pageParameters.remove(CACHEABLE);
        }
        if (zeuzPageParameters != null) {
            pageParameters.putAll(zeuzPageParameters);
            if (pageParameters.containsKey("locale")) {
                pageParameters.remove("locale");
            }
        }

        pageParameters.add("locale", locale.getLanguage());
        return pageParameters;

}
Okay so 4 simple steps are needed to make our wicket pages cachable:

  1. Make a method that can determine if a page are cachable or not
  2. Keep a reference to the page parameters the page were initialized with.
  3. Use bookmarkablePageLink’s so that url’s are stable
  4. This is where the magic are done, add the cachable parameter to appropriate pages, notice that if you have a multilingual application you need that as a parameter otherwise the locale of the pages will be the one that last caused a miss.

Note : I had to set this to get stable parameter positions in urls:

        // Be able to sort page parametes
        UnitTestSettings.setSortUrlParameters(true);

Okay so now our wicket pages can be cached, now we just setup the cache:

add in ehcache.xml

<cache name=”SimplePageCachingFilter” overflowToDisk=”true” maxElementsInMemory=”500″ timeToLiveSeconds=”86400″ timeToIdleSeconds=”43200″/>

if you want define flush methods in cacheContex.xml:

    <ehcache:flushing cacheNames="SimplePageCachingFilter" methodFQN="zeuzgroup.core.provider.IDBDao.persistExercise*" when="after"/>

For me this made the page I talked about earlier go from 4s to 0.2s to display.

Conclusion

So I tried several approaches before comming to the approach showed above (regarding wicket). I tried creating a custom a IRequestEncodingStrategy, did’nt work for me but it’s my fault nothing todo with wicket. Sometimes simple are better I guess. An annoying thing were that apparently that my pages when in danish locale were’nt encoded with html entities (this caused chars like æ ø å to get corrupted), i’ve submitted a patch to wicket to support this http://issues.apache.org/jira/browse/WICKET-1795 , it’s just for component though a general setting would be nice. I think above are pretty straight forward, but of course it would be nice if wicket support something like it out of the box, but then again it requires many thing that only you as the developer can decide. Using above approach you’re free to chose ehwebcachefilter like i did or something else like Apache http, if you dont select ehcache, you’ll loose the evict option. But there might be other options. The above approach should be usable with other web frameworks aswell.





Hibernate Trouble?

30 03 2008

So for my very own small personal project, http://www.træningslog.dk I am using Hibernate as persistence provider. But I keep bumping into problems when it comes to polymorphism, ive already stumpled over this:

http://opensource.atlassian.com/projects/hibernate/browse/ANN-720

And now it looks like i’ve fallen into another one. More on this later.

I guess the short conclusion are that i’ll switch to OpenJPA, and see how it fits instead.. However I like the criteria api from hibernate very much, and would hate to miss out on that….








Follow

Get every new post delivered to your Inbox.