Spring – MyBatis integrace a něco navíc

Článek popíše možnosti integrace Spring a MyBatis frameworků a představí užitečné rozšíření – factory na automatickou registraci Mapper rozhranní implementovaných XML definicí.

Pokud chceme na projektu integrovat Spring a MyBatis frameworky, nemáme zatím k dispozici oficiální Springem podporované řešení. Spring označoval MyBatis za “moving target”, ale oznámil, že ho bude podporovat ve Spring Data projektu. MyBatis komunita zatím zahájila vlastní snahu a její implementaci integrace už jde používat. Máme tedy k dispozici:

Protože hotové řešení potřebujeme tady a teď, používáme na aktuálním projektu první zmíněnou verzi, která k naší spokojenosti funguje s MyBatisem 3.0.2 a Springem 3.0.4. Použití je disktuváno v rámci JIRA issue, XML konfigurace pro představu může vypadat takto:

<bean id="sqlSessionFactory" class="org.springframework.orm.ibatis3.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <property name="configLocation" value="classpath:sale-mybatis-config.xml" />
   <property name="mapperLocations">
   <list><value>classpath:sale/*-mapper.xml</value></list>
   </property>
</bean>
<bean id="baseDao" abstract="true" class="org.springframework.orm.ibatis3.MapperFactoryBean">
   <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="saleDao" parent="baseDao">
   <property name="mapperInterface" value="sale.SaledDao" />
</bean>

Něco navíc

Pokud pracujete s mnoha Dao třídami (resp. s Mappery), XML konfigurace se začne “protivně” rozrůstat o jejich definice. Nabízí se možnost označit mapper rozhranní vhodnou anotací a registraci přenechat nějaké factory, která by to zvládla sama. Cílem je použít místo abstraktního baseDao a konkrétního saleDao (a dalších) z předchozího příkladu podobnou konstrukci:

<bean class="mybatis.MyBatisDaoFactory">
   <property name="basePackage" value="sale.dao"/>
   <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

Pro označení mapper rozhranní jsme zavedli anotaci @MyBatisDao:

@MyBatisDao
public interface SaleDao {
   Long create(Sale sale);
   ...
}

Implementace MyBatisDaoFactory je nakonec docela jednoduchá. K nalezení kandidátů na mapper použijeme classpath scanning, k registraci jejich implementací potom BeanDefinitionRegistryPostProcessor, který dovoluje přidávat do BeanFactory nové programově vytvořené instance. Samotné vytvoření instance mapperu necháme na org.springframework.orm.ibatis3.MapperFactoryBean, stejně jako v předchozím příkladu.

Klíčová metoda postProcessBeanDefinitionRegistry potom vypadá docela jednoduše.

public class MyBatisDaoFactory implements BeanDefinitionRegistryPostProcessor {
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		Iterable<Class> classes = ClasspathUtils.getClasses(basePackage);
		for (Class clazz : classes) {
			if (clazz.isAnnotationPresent(MyBatisDao.class)) {
				BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class).getBeanDefinition();
				beanDefinition.getPropertyValues().addPropertyValue("sqlSessionFactory", sqlSessionFactory);
				beanDefinition.getPropertyValues().addPropertyValue("mapperInterface", clazz.getCanonicalName());
				registry.registerBeanDefinition(clazz.getName(), beanDefinition);
			}
		}
	}
}

Pomocná třída ClasspathUtils implementuje classpath scanning podle popisu na StackOverflow. Pokud se chcete vlastní implementaci vyhnout a nevadí vám závislost na API MyBatisu, můžete využít jeho třídu ResolverUtil.

Tento příklad také ukazuje, jak obecně z anotovaných rozhranní vytvořit Spring beany, pokud se jejich implementaci tvoří dynamicky.

Shrnutí

Článek popsal stav integrace Spring a MyBatis frameworků a představil jednoduché rozšíření pro automatické vyhledání a registraci mapperů implementovaných XML definicí.

Používáte na projektu Spring a MyBatis dohromady? Jak řešíte integraci? Podělte se o své zkušenosti v diskuzi pod článkem.

Odkazy

Napsat komentář

Vaše emailová adresa nebude zveřejněna.

 

 

Můžete použít tyto HTML tagy: <strong> <a href="" title="">
Chcete li do komentáře přidat zdrojový kód, obalte ho tagem [sourcecode language="jazyk"]


*

  1. Eduardo: 13.10. 2010

    Hi there Tomas. I had just now started to write a component scan for mappers. I suggested it in Springs JIRA and also added an issue on mybatis.
    But googling… to my surprise I found you already did it. Would you mind if I add your BeanDefinitionRegistryPostProcessor to MyBatis project?
    Thanks!

  2. Tomáš Piňos: 13.10. 2010

    Hi Eduardo, I’ll be happy if the mapper scanning makes it to the integration project. Feel free to add the processor. If it helps, I can send you the package provided with unit tests.