首先创建一个MybatisConfiguration.java
package org.coolerwu.outsource.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* @author coolerwu on 2018/6/8.
* @version 1.0
* @time 23:40
*/
@Configuration
public class MybatisConfiguration {
@Bean("dataSource")
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/outsource?useSSL=false");
dataSource.setUser("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:org/coolerwu/outsource/mapping/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("org.coolerwu.outsource.mapping");
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
return mapperScannerConfigurer;
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
**注意:**在进行MapperScan扫描的时候,会出现这样两个个警告:
No MyBatis mapper was found in '[org.coolerwu.outsource]' package. Please check your configuration
Cannot enhance @Configuration bean definition 'mybatisConfigruation' since its singleton instance
has been created too early. The typical cause is a non-static @Bean method with a
BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
这是因为MapperScannerConfigurer是BeanFactoryPostProcessor的一个实现,如果配置类中出现BeanFactoryPostProcessor,会破坏默认的 post-processing 。
最简单的解决方式是使用 @MapperScan 注解代替 MapperScannerConfigurer 的 bean 配置。
关于@MapperScan的源代码:
/**
* Copyright 2010-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.spring.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.Import;
/**
* Use this annotation to register MyBatis mapper interfaces when using Java
* Config. It performs when same work as {@link MapperScannerConfigurer} via
* {@link MapperScannerRegistrar}.
*
* <p>Configuration example:</p>
* <pre class="code">
* @Configuration
* @MapperScan("org.mybatis.spring.sample.mapper")
* public class AppConfig {
*
* @Bean
* public DataSource dataSource() {
* return new EmbeddedDatabaseBuilder()
* .addScript("schema.sql")
* .build();
* }
*
* @Bean
* public DataSourceTransactionManager transactionManager() {
* return new DataSourceTransactionManager(dataSource());
* }
*
* @Bean
* public SqlSessionFactory sqlSessionFactory() throws Exception {
* SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
* sessionFactory.setDataSource(dataSource());
* return sessionFactory.getObject();
* }
* }
* </pre>
*
* @author Michael Lanyon
* @author Eduardo Macarron
*
* @since 1.2.0
* @see MapperScannerRegistrar
* @see MapperFactoryBean
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise
* annotation declarations e.g.:
* {@code @EnableMyBatisMapperScanner("org.my.pkg")} instead of {@code
* @EnableMyBatisMapperScanner(basePackages= "org.my.pkg"})}.
*/
String[] value() default {};
/**
* Base packages to scan for MyBatis interfaces. Note that only interfaces
* with at least one method will be registered; concrete classes will be
* ignored.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* The {@link BeanNameGenerator} class to be used for naming detected components
* within the Spring container.
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* This property specifies the annotation that the scanner will search for.
* <p>
* The scanner will register all interfaces in the base package that also have
* the specified annotation.
* <p>
* Note this can be combined with markerInterface.
*/
Class<? extends Annotation> annotationClass() default Annotation.class;
/**
* This property specifies the parent that the scanner will search for.
* <p>
* The scanner will register all interfaces in the base package that also have
* the specified interface class as a parent.
* <p>
* Note this can be combined with annotationClass.
*/
Class<?> markerInterface() default Class.class;
/**
* Specifies which {@code SqlSessionTemplate} to use in the case that there is
* more than one in the spring context. Usually this is only needed when you
* have more than one datasource.
*/
String sqlSessionTemplateRef() default "";
/**
* Specifies which {@code SqlSessionFactory} to use in the case that there is
* more than one in the spring context. Usually this is only needed when you
* have more than one datasource.
*/
String sqlSessionFactoryRef() default "";
/**
* Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean.
*
*/
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
}
我们可以找到basePackages是指定包,sqlSessionFactoryRef是指定他的SqlSessionFactory,把他放在MybatisConfiguration.java类上面
@MapperScan(basePackages = "org.coolerwu.outsource.mapping",
sqlSessionFactoryRef = "sqlSessionFactory")
完整的配置类注解代码如下:
package org.coolerwu.outsource.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* @author coolerwu on 2018/6/8.
* @version 1.0
* @time 23:40
*/
@Configuration
@MapperScan(basePackages = "org.coolerwu.outsource.mapping", sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfiguration {
@Bean("dataSource")
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/outsource?useSSL=false");
dataSource.setUser("root");
dataSource.setPassword("wulang");
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:org/coolerwu/outsource/mapping/*.xml"));
return sqlSessionFactoryBean.getObject();
}
// @Bean
// public MapperScannerConfigurer mapperScannerConfigurer() {
// MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
// mapperScannerConfigurer.setBasePackage("org.coolerwu.outsource.mapping");
// mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
// return mapperScannerConfigurer;
// }
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。
OutsourceApplication.java 如下:
package org.coolerwu.outsource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
public class OutsourceApplication {
public static void main(String[] args) {
SpringApplication.run(OutsourceApplication.class, args);
}
}
关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。
在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
然后在Service中,被 @Transactional 注解的方法,将支持事务。如果注解在类上,则整个类的所有方法都默认支持事务。
UserService.java 代码如下:
package org.coolerwu.outsource.service;
/**
* @author coolerwu on 2018/6/7.
* @version 1.0
* @time 16:33
*/
public interface UserService {
/**
* 用户登录
* @param loginName
* @param loginPass
* @return
*/
int login(String loginName, String loginPass);
}
UserServiceImpl.java 代码如下:
package org.coolerwu.outsource.service.service;
import org.coolerwu.outsource.mapping.UserMapper;
import org.coolerwu.outsource.po.User;
import org.coolerwu.outsource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author coolerwu on 2018/6/7.
* @version 1.0
* @time 16:33
*/
@Service("userService")
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = {Exception.class})
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public int login(String loginName, String loginPass) {
User publisher = userMapper.login(loginName, loginPass);
if (publisher == null) {
return 0;
}
return 1;
}
}
注意:这里的userMapper的自动装配可以会提示你找不到该bean,不用理会;如果强迫症的话,可以在UserMapper.java添加@Repository就可以消除。UserMapper.java 代码如下:
package org.coolerwu.outsource.mapping;
import org.apache.ibatis.annotations.Param;
import org.coolerwu.outsource.po.User;
import org.springframework.stereotype.Repository;
/**
* @author coolerwu on 2018/6/7.
* @version 1.0
* @time 16:36
*/
@Repository
public interface UserMapper {
User login(@Param("loginName") String loginName, @Param("loginPass") String loginPass);
}
另外附上UserMapper.xml 代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.coolerwu.outsource.mapping.UserMapper">
<select id="login" resultType="org.coolerwu.outsource.po.User">
SELECT * FROM tb_user WHERE LOGINNAME = #{loginName} AND LOGINPASS = #{loginPass}
</select>
</mapper>
以及UserController.java 代码如下:
package org.coolerwu.outsource.controller;
import org.coolerwu.outsource.extra.Msg;
import org.coolerwu.outsource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
/**
* @author coolerwu on 2018/6/7.
* @version 1.0
* @time 16:27
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/login")
public Msg login(@RequestParam("loginName") String loginName,
@RequestParam("loginPass") String loginPass,
HttpSession session) {
int i = userService.login(loginName, loginPass);
if (i == 1) {
session.setAttribute("loginName", loginName);
session.setMaxInactiveInterval(3600);
return Msg.success();
}
return Msg.fail();
}
}
这样完整的SSM搭建就完成了,注解不理解的,多去百度,有很多解释的,因此我没有必要在解释一遍了!