|
Spring
An introduction to MyBatis integration with Spring
Introduction to MyBatis-SpringMyBatis-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 SetupTo 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 InstallationMyBatis-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> | |
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
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.
Will the Spring official integration be the same?
木有官方的支持文档吗
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.
Add two datasources, two SqlSessionFactories? and a JtaTransaction? manager (in the case you need transactions).
Thanks Eduardo that works. I had to add another instance of SqlSessionFactory? to make it work. Cheers!
Were are the myBatis annotations?
what annotations?
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.
Thanks Eduardo this works.
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.
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
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.
hi gpepus, could you fill an issue with this an provide a basic test?
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?
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]my spring config file content: <bean id="mobileDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<bean id="ipDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<bean id="ipDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- enable component scanning (beware that this does not enable mapper scanning!) -->
mapper packages: com.sivyer.app.number.persistence.appxxxxx.xxxxxMapper service packages: com.sivyer.app.number.service.appxxxxx.xxxxService