My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Spring  
An introduction to MyBatis integration with Spring
Updated Yesterday (18 hours ago) by eduardo....@gmail.com

Introduction to MyBatis-Spring

MyBatis-Spring helps you integrate your MyBatis code seamlessly with Spring. Using the classes in this library, Spring will load the necessary MyBatis factory and session classes for you. This library also provides an easy way to inject MyBatis data mappers into your service beans. Finally, MyBatis-Spring will handle transactions and translate MyBatis exceptions into Spring DataAccessExceptions.

Quick Setup

To use MyBatis with Spring you need at least two things defined in the Spring application context: an SqlSessionFactory and at least one data mapper class. In MyBatis-Spring, an SqlSessionFactoryBean is used to create an SqlSessionFactory. To configure the factory bean, put the following in the Spring XML configuration file:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>

Notice that the SqlSessionFactory requires a DataSource. This can be any DataSource and should be configured just like any other Spring database connection.

Assume you have a data mapper class defined like the following:

public interface UserMapper {
  @Select("SELECT * FROM user WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
}

This interface is added to Spring using a MapperFactoryBean like the following:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

Note that the mapper class specified must be an interface, not an actual implementation class. In this example, annotations are used to specify the SQL, but a MyBatis mapper XML file could also be used.

Once configured, you can inject mappers directly into your business/service objects in the same way you inject any other Spring bean. The MapperFactoryBean handles creating an SqlSession as well as closing it. If there is a Spring transaction in progress, the session will also be committed or rolled back when the transaction completes. Finally, any exceptions will be translated into Spring DataAccessExceptions.

Calling MyBatis data methods is now only one line of code:

public class FooServiceImpl implements FooService {

    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    public User doSomeBusinessStuff(String userId) {
        return this.userMapper.getUser(userId);
    }

}

More info?

Download the pdf manual. You can find it in downloads. http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DSpring

And have a look at JPetStore 6 that is built on top of MyBatis, Spring and Stripes: http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DSample

Installation

MyBatis-Spring code and detailed documentation is available at the downloads section.

To use the MyBatis-Spring module, you just need to include the mybatis-spring jar file and its dependencies in the classpath.

If you are using Maven just add the following dependency to your pom.xml:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.1.0</version>
</dependency>
Comment by matias...@gmail.com, Jan 7, 2011

Notice that mybatis-spring:1.0.0 requires mybatis:3.0.4. If you try it with mybatis:3.0.3 or prior versions you will get this exception:

java.lang.NoSuchMethodError?: org.apache.ibatis.builder.xml.XMLConfigBuilder.<init>(Ljava/io/InputStream?;Ljava/lang/String;Ljava/util/Properties;)V

Comment by pete4...@gmail.com, Aug 9, 2011

Couldn't you keep the mybatis-spring version similar to the mybatis version? this will make the choosing of the right version much easier?

e.g. mybatis-3.0.5 -> mybatis-spring-3.5.0, 3.0.5-1, 3.0.5-2 etc.

Comment by MT.sna...@gmail.com, Aug 12, 2011

Will the Spring official integration be the same?

Comment by write2da...@gmail.com, Sep 28, 2011

木有官方的支持文档吗

Comment by mvayd...@gmail.com, Oct 21, 2011

Does anyone know how to configure spring to use 2 different databases? Much appreciated if you could provide some sample spring-config.xml containing 2 datasources that points to 2 different db schemas.

Comment by project member eduardo....@gmail.com, Oct 21, 2011

Add two datasources, two SqlSessionFactories? and a JtaTransaction? manager (in the case you need transactions).

Comment by mvayd...@gmail.com, Oct 21, 2011

Thanks Eduardo that works. I had to add another instance of SqlSessionFactory? to make it work. Cheers!

Comment by jlopes...@COMCAST.NET, Oct 26, 2011

Were are the myBatis annotations?

Comment by project member eduardo....@gmail.com, Oct 26, 2011

what annotations?

Comment by project member eduardo....@gmail.com, Nov 11, 2011

Try this: <select id="someId" parameterType="java.lang.String"> select columnname from table1 where columname2 = ${value} </select>

Note the $ instead of the usual #

BTW please ask these type of questions in the users ML you will get help much faster.

Comment by mvayd...@gmail.com, Nov 14, 2011

Thanks Eduardo this works.

Comment by mvayd...@gmail.com, Dec 6, 2011

Eduardo, how can I manually rollback and commit my insert transaction if I'm using MyBatis?-Spring integration since Spring is handling them implicitly? Please provide code samples. Many thanks in advance for this very important tasks in my project.

Comment by project member eduardo....@gmail.com, Dec 6, 2011

Hi. As you may have already notice SqlSession?.commit()/rollback() cannot be used. You must use Spring's API for programmatic transaction management. Have a look at Spring reference for more info.

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-programmatic

Comment by gpe...@gmail.com, Jan 6, 2012

What version of the MyBatis? are you using? 3.0.6

Please describe the problem. Unit tests are best!

I had implemented some SQL inserts using DAO and DAO.MyBatis? implementation. I had also implemented AOP to automatically set updatedBy and updatedDate on all my model objects. All of this worked fine including the AOP piece. I.e. AOP fired onPreInsert when doing the insert with a DAO/DAO mybatis implementation.

Then I ran into a situation which really made me rethink the DAO approach and instead use Mappers .. MapperFactoryBean? .. Proxy etc. I implemented this and ran into an issue with AOP .. it appears when using MapperFactoryBean? .. that the MyBatis?/Spring or perhaps just MyBatis? .. not sure which ... isn't picking up on the insert .. so that when my @Before .. based on @Pointcut runs in synchronization with my MapperBean? its not firing my @Before .. onPreInsert() .. method. So my updatedBy and updatedDate objects aren't getting set.

In other words with the MapperFactorBean? approach vs.SqlSessionDaoSupport? the insert event isnt being picked up by AOP and my Pointcut isn't firing.

All I did in my AOP class was change the @Pointcut routine to look at com.fa.mapper. instead of com.fa.dao.. This means that somehow the Proxy insert (or other CRUD) activity of the MapperFactoryBean? isnt being detected by AOP.

Any and all thoughts would be appreciated.

Comment by project member eduardo....@gmail.com, Jan 6, 2012

hi gpepus, could you fill an issue with this an provide a basic test?

Comment by oak...@gmail.com, Feb 26, 2012

how can i config with spring3 with multi datasource support? I test ,but has error error content: 2012-2-26 17:56:46 org.springframework.context.support.AbstractApplicationContext? prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext?@32fb4f: startup date Feb 26 17:56:46 CST 2012?; root of context hierarchy 2012-2-26 17:56:46 org.springframework.beans.factory.xml.XmlBeanDefinitionReader? loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring/applicationContext.xml] 2012-2-26 17:56:46 org.springframework.beans.factory.xml.XmlBeanDefinitionReader? loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring/spring_ip.xml] 2012-2-26 17:56:46 org.springframework.beans.factory.support.DefaultListableBeanFactory? preInstantiateSingletons 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory?@fd68b1: defining beans [mobileDataSource,mobileSessionFactory,ipDataSource,ipSessionFactory,ipService,mobileService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0?,org.springframework.transaction.interceptor.TransactionInterceptor#0?,org.springframework.transaction.config.internalTransactionAdvisor,org.mybatis.spring.mapper.MapperScannerConfigurer#0?,ipMapper,mobileMapper]; root of factory hierarchy 2012-2-26 17:56:47 org.springframework.jdbc.datasource.DriverManagerDataSource? setDriverClassName 信息: Loaded JDBC driver: com.mysql.jdbc.Driver 2012-2-26 17:56:47 org.springframework.jdbc.datasource.DriverManagerDataSource? setDriverClassName 信息: Loaded JDBC driver: com.mysql.jdbc.Driver 2012-2-26 17:56:47 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry? destroySingletons 信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory?@fd68b1: defining beans [mobileDataSource,mobileSessionFactory,ipDataSource,ipSessionFactory,ipService,mobileService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0?,org.springframework.transaction.interceptor.TransactionInterceptor#0?,org.springframework.transaction.config.internalTransactionAdvisor,org.mybatis.spring.mapper.MapperScannerConfigurer#0?,ipMapper,mobileMapper]; root of factory hierarchy Exception in thread "main" java.lang.ExceptionInInitializerError?

at com.sivyer.sample.multi.DatasourceTest?.main(DatasourceTest?.java:10)
Caused by: org.springframework.beans.factory.BeanCreationException?: Error creating bean with name 'ipService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException?: Could not autowire field: com.sivyer.app.number.persistence.ip.IpMapper? com.sivyer.app.number.service.ip.IpService?.mapper; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException?: No matching bean of type [com.sivyer.app.number.persistence.ip.IpMapper?] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} Related cause: org.springframework.beans.factory.BeanCreationException?: Error creating bean with name 'mobileMapper': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException?: Could not autowire method: public final void org.mybatis.spring.support.SqlSessionDaoSupport?.setSqlSessionFactory(org.apache.ibatis.session.SqlSessionFactory?); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException?: No unique bean of type [org.apache.ibatis.session.SqlSessionFactory?] is defined: expected single matching bean but found 2: [mobileSessionFactory, ipSessionFactory] Related cause: org.springframework.beans.factory.BeanCreationException?: Error creating bean with name 'ipMapper': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException?: Could not autowire method: public final void org.mybatis.spring.support.SqlSessionDaoSupport?.setSqlSessionFactory(org.apache.ibatis.session.SqlSessionFactory?); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException?: No unique bean of type [org.apache.ibatis.session.SqlSessionFactory?] is defined: expected single matching bean but found 2: [mobileSessionFactory, ipSessionFactory]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor?.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor?.java:285) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory?.populateBean(AbstractAutowireCapableBeanFactory?.java:1074) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory?.doCreateBean(AbstractAutowireCapableBeanFactory?.java:517) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory?.createBean(AbstractAutowireCapableBeanFactory?.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory?$1.getObject(AbstractBeanFactory?.java:291) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry?.getSingleton(DefaultSingletonBeanRegistry?.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory?.doGetBean(AbstractBeanFactory?.java:288) at org.springframework.beans.factory.support.AbstractBeanFactory?.getBean(AbstractBeanFactory?.java:190) at org.springframework.beans.factory.support.DefaultListableBeanFactory?.preInstantiateSingletons(DefaultListableBeanFactory?.java:580) at org.springframework.context.support.AbstractApplicationContext?.finishBeanFactoryInitialization(AbstractApplicationContext?.java:895) at org.springframework.context.support.AbstractApplicationContext?.refresh(AbstractApplicationContext?.java:425) at org.springframework.context.support.ClassPathXmlApplicationContext?.<init>(ClassPathXmlApplicationContext?.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext?.<init>(ClassPathXmlApplicationContext?.java:83) at com.sivyer.util.AppContext?.<clinit>(AppContext?.java:10) ... 1 more

my spring config file content: <bean id="mobileDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/mobile?useUnicode=true&amp;characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="root" />
</bean>
<!-- define the SqlSessionFactory? --> <bean id="mobileSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="mobileDataSource" /> <property name="typeAliasesPackage" value="com.sivyer.app.number.domains.mobile" /> <property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>

<bean id="ipDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/ip?useUnicode=true&amp;characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="root" />
</bean>

<!-- define the SqlSessionFactory? -->
<bean id="ipSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="ipDataSource" /> <property name="typeAliasesPackage" value="com.sivyer.app.number.domains.ip" /> <property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>

<bean id="ipDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/ip?useUnicode=true&amp;characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="root" />
</bean>

<!-- define the SqlSessionFactory? -->
<bean id="ipSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="ipDataSource" /> <property name="typeAliasesPackage" value="com.sivyer.app.number.domains.ip" /> <property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>

<!-- enable component scanning (beware that this does not enable mapper scanning!) -->

<context:component-scan base-package="com.sivyer.app.number.service" />
<!-- enable autowire --> <context:annotation-config />

<!-- enable transaction demarcation with annotations --> <tx:annotation-driven />
<!-- scan for mappers and let them be autowired --> <!-- Rules: ..persistence.appxxxx.Xxxxx -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.sivyer.app.number.persistence" />
</bean>

mapper packages: com.sivyer.app.number.persistence.appxxxxx.xxxxxMapper service packages: com.sivyer.app.number.service.appxxxxx.xxxxService


Sign in to add a comment
Powered by Google Project Hosting