Spring、Spring MVC、MyBatis 整合
一、依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>ssm</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--spring mvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.5.RELEASE</version> </dependency> <!--事务管理等--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!--简化pojo类--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.6</version> <scope>provided</scope> </dependency> <!--mybatis整合spring--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.0</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.0</version> </dependency> <!--jdbc驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency> <!--druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.14</version> </dependency> <!--日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>1.7.26</version> </dependency> </dependencies> <properties> <!--编码格式--> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <!--tomcat 插件方式运行需指定为 war 包--> <packaging>war</packaging> <build> <plugins> <!-- 指定jdk --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <encoding>UTF-8</encoding> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <!--tomcat插件--> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <ignorePackaging>true</ignorePackaging> <port>80</port> <path>/ssm</path> <server>tomcat7</server> <charset>UTF-8</charset> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> </plugins> </build> </project>
二、配置
数据库信息 db.properties
db.url=jdbc:mysql://192.168.8.136:3306/mybatis?allowMultiQueries=true db.username=root db.password=root
mybatis属性配置,也可不配置 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- 本地(一级)缓存作用域,默认 SESSION,会缓存一个会话(SqlSession)中执行的所有查询。 设置为 STATEMENT,会话仅作用在语句执行上,对 SqlSession 的调用将不会共享数据,可认为是禁用一级缓存 --> <setting name="localCacheScope" value="SESSION"/> <!-- 控制台打印SQL --> <setting name="logImpl" value="STDOUT_LOGGING"/> <!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true --> <setting name="useColumnLabel" value="true"/> <!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE:不隐射 PARTIAL:部分 FULL:全部 --> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新) --> <setting name="defaultExecutorType" value="SIMPLE"/> <!-- 使用驼峰命名法转换字段。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER,插入空值时不需要指定类型 --> <setting name="jdbcTypeForNull" value="NULL"/> <!-- 是否允许单条sql 返回多个数据集 (取决于驱动的兼容性) default:true --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false --> <setting name="useGeneratedKeys" value="false"/> </settings> </configuration>
注解配置类,tomcat 启动时会加载此类,然后才有后续的操作
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { // spring 配置 return new Class<?>[]{RootConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { // spring mvc 配置 return new Class<?>[]{ServletConfig.class}; } @Override protected String[] getServletMappings() { // DispatcherServlet 拦截路径,/* 拦截所有,/ 会排除 *.jsp 文件 return new String[]{"/"}; } }
spring 配置
// 开启事务管理 @EnableTransactionManagement // 加载 properties 文件 @PropertySource("classpath:db.properties") // 扫描包路径,spring 扫描除 controller 层以外的,spring 不可从子容器(spring mvc)中获取 bean @ComponentScan(basePackages = {"ssm.service", "ssm.pojo", "ssm.dao"}) public class RootConfig { /** * SqlSession 工厂 * @param dataSource 数据源,会在 IOC 中获取 */ @Bean public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) throws IOException { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); // 设置 MyBatis 配置文件路径 factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml")); // 设置 SQL 映射文件路径 factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); // 设置 JavaBean 类型别名,在 SQL 映射文件中就不用写全类名 factoryBean.setTypeAliasesPackage("ssm.pojo"); return factoryBean; } /** * Druid 数据源 */ @Bean public DataSource getDataSource(@Value("${db.username}") String name, @Value("${db.password}") String password, @Value("${db.url}") String url) { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(name); dataSource.setPassword(password); return dataSource; } /** * 扫描所有 mapper 接口的实现,让这些 mapper 能够自动注入 */ @Bean public MapperScannerConfigurer getMapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("ssm.dao"); return mapperScannerConfigurer; } /** * 事务管理 */ @Bean public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } /** * 配置一个可以进行批量执行的 sqlSession */ @Bean public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception { /** * Simple Executor -- SIMPLE 普通的执行器,默认 * Reuse Executor -执行器会重用预处理语句(prepared statements) * Batch Executor --批量执行器 */ SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject(), ExecutorType.BATCH); return sessionTemplate; } }
spring mvc 配置,需实现 WebMvcConfigurer 接口
// 开启事务管理 @EnableTransactionManagement // 加载 properties 文件 @PropertySource("classpath:db.properties") // 扫描包路径,spring 扫描除 controller 层以外的,spring 不可从子容器(spring mvc)中获取 bean @ComponentScan(basePackages = {"ssm.service", "ssm.pojo", "ssm.dao"}) public class RootConfig { /** * SqlSession 工厂 * @param dataSource 数据源,会在 IOC 中获取 */ @Bean public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) throws IOException { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); // 设置 MyBatis 配置文件路径 factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml")); // 设置 SQL 映射文件路径 factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); // 设置 JavaBean 类型别名,在 SQL 映射文件中就不用写全类名 factoryBean.setTypeAliasesPackage("ssm.pojo"); return factoryBean; } /** * Druid 数据源 */ @Bean public DataSource getDataSource(@Value("${db.username}") String name, @Value("${db.password}") String password, @Value("${db.url}") String url) { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(name); dataSource.setPassword(password); return dataSource; } /** * 扫描所有 mapper 接口的实现,让这些 mapper 能够自动注入 */ @Bean public MapperScannerConfigurer getMapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("ssm.dao"); return mapperScannerConfigurer; } /** * 事务管理 */ @Bean public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } /** * 配置一个可以进行批量执行的 sqlSession */ @Bean public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception { /** * Simple Executor -- SIMPLE 普通的执行器,默认 * Reuse Executor -执行器会重用预处理语句(prepared statements) * Batch Executor --批量执行器 */ SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject(), ExecutorType.BATCH); return sessionTemplate; } }
三、测试
1.dao层
@Repository public interface UserMapper { public User getUserById(User user); public boolean addUserById(User user); }
对应的 SQL 映射文件
<?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"> <!-- namespace 对应接口文件的全路径 --> <mapper namespace="ssm.dao.UserMapper"> <select id="getUserById" parameterType="user" resultType="user"> select * from user where user.id = ${id} </select> <insert id="addUserById" parameterType="user"> insert into user(name,age) values(#{name},#{age}) </insert> </mapper>
2.实体层
@Getter @Setter @ToString public class User { private Integer id; private String name; private Integer age; }
3.service 层
@Service public class UserManagerService { @Autowired private UserMapper userMapper; @Autowired private SqlSessionTemplate sqlSessionTemplate; // 使用事务 @Transactional public User getUserById(){ User user = new User(); user.setId(1); userMapper.getUserById(user); user = sqlSessionTemplate.selectOne("ssm.dao.UserMapper.getUserById",user); userMapper.addUserById(user); // 异常回退 int i = 3/0; return user; } }
4.controller 层
@Controller public class HelloWorld { @Autowired private UserManagerService userManagerService; @ResponseBody @RequestMapping(value = "/hw",method = RequestMethod.GET) public String hw() { return userManagerService.getUserById().toString(); } }
插件方式启动 tomcat
项目结构