SSM-CRUD入门项目——环境搭建
一、项目概述
项目功能点:
1.分页
2.数据校验:
jQuery前端校验+JSR303后端校验
3.ajax
4.RESTful风格的URI
技术点:
1.基础框架——SSM
2.数据库——MySQL
3.前端框架bootstrap快速搭建前端界面
4.项目构建工具——maven
5.mybatis分页插件——pagehelper进行分页
6.mybatsi-generator逆向工程进行mapper生成
二、环境搭建
1.构建一个maven工程(如何构建web的maven工程参见Maven的博客)
//注意点:打包方式请记得选择war包,请配置为标准的web程序目录结构,自己写结束标签
(去掉原来web-app标签下的/,改为闭合标签</web-app>)
此时的web.xml如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> </web-app>
2.引入依赖
spring
springMVC
mybatis
连接池+数据库驱动
其它jar(jstl,servlet-api,junit等等)
(上maven仓库中搜索相关的依赖坐标信息)
//注意: maven servlet-api 和 javax.servlet-api区别 :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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>cn.jiangbei</groupId> <artifactId>ssm-crud</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!-- 引入分页插件pageHelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.0.0</version> </dependency> <!-- 引入spring springMVC依赖 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.7.RELEASE</version> </dependency> <!-- spring-JDBC --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.7.RELEASE</version> </dependency> <!-- spring切面 spring-aspects模块 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.7.RELEASE</version> </dependency> <!-- spring-test --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.7.RELEASE</version> <scope>test</scope> </dependency> <!-- 引入Mybatis --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.2</version> </dependency> <!-- MBG --> <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.5</version> </dependency> <!-- spring整合mybatis的包 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <!-- 数据库连接池与驱动包,注意c3p0是c3p0 c3p0下的包(版本有问题请更换版本) --> <!-- https://mvnrepository.com/artifact/c3p0/c3p0 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.41</version> </dependency> <!-- jstl(和c3p0一样,是jstl>jstl下的), servlet-api(请注意正确引入), junit --> <!-- https://mvnrepository.com/artifact/jstl/jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/taglibs/standard --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api --> <!-- <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> --> <!-- 因为sprngTest要求更高版本的servlet,我们将其替换为3.0以上的版本 --> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!-- <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1</version> <scope>provided</scope> </dependency> --> <!-- jsp依赖 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 引入jackson的包 --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.8</version> </dependency> <!-- 后端校验JSR303的实现——hibernate-validator依赖 如果是tomcat7以下的服务器,需要额外给服务器的Lib包中替换新的EL --> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.4.1.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>8080</port> <path>/ssm-crud</path> <uriEncoding>UTF-8</uriEncoding> <finalName>ssm-crud</finalName> <server>tomcat7</server> </configuration> </plugin> </plugins> </build> </project>
3.引入bootstrap环境
下载解压后,解压至项目web-app下static文件夹
具体引入css与js可以参见官网的基本模板
引入完成的情况如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- 先引入jQuery,再引入js-->
<script type="text/javascript" src="static/bootstrap/js/jquery.min.js"> </script>
<script src="static/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
</body>
</html>
4.编写整合的配置文件
web.xml:
1.配置启动spring容器>(通过springIDE快速编写相关的监听器)——在对应位置定义spring配置文件
2.配置前端控制器——用来拦截请求(url设置为/),这里使用默认的命名与位置(默认命名为${servlet-name}-Servlet.xml,位置与web.xml同级,即位WEB-INF下,当然可以自己指定。)
3.配置springMVC的字符编码过滤器(参见springMVC day01博客第五章)
4.配置HiddenHttpMethodFilter,处理DELETE 和 PUT请求。
//注意多个过滤器时,按照先后顺序,而处理编码的是必须在前面的。
至此,web.xml配置完成:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- 1.启动spring容器 --> <!-- needed for ContextLoaderListener --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- Bootstraps the root web application context before servlet initialization --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 2.配置springMVC前端控制器 --> <!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 3.springMVC的字符编码过滤器 ,在所有过滤器之前--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 4.配置HiddenHttpMethodFilter过滤器,处理RESTful风格的请求 --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
//补充:
<!-- 若不适用默认的,可以通过init-param进行初始化位置的定义 -->
<!-- <init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param> -->
【更新】:springMVC的前端控制器的url-pattern必须为 / ,详见springMVC博客。
<!-- 可以配置/ ,此工程 所有请求全部由springmvc解析,此种方式可以实现 RESTful方式,需要特殊处理对静态文件的解析不能由springmvc解析
可以配置*.do或*.action,所有请求的url扩展名为.do或.action由springmvc解析,此种方法常用 不可以/*,如果配置/*,返回jsp也由springmvc解析,这是不对的。 -->
使用自定义位置的sprinMVC扫描如下:
<!-- MVC Servlet --> <servlet> <servlet-name>springServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/spring-mvc*.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
dispatcherServlet-servlet.xml:
1.包扫描(只扫描controller的注解)
2.三大件
3.静态资源访问
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- springMVC的配置文件,跳转逻辑有关的 --> <!-- 配置包扫描 --> <context:component-scan base-package="cn.crud" use-default-filters="false"> <!-- 配置只扫描@Controller注解 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 配置三大件 --> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 两个标配 --> <!-- 1.配置注解驱动(处理器适配器和映射器),还有更多高级特性 --> <mvc:annotation-driven/> <!-- 2.配置静态资源访问 --> <mvc:default-servlet-handler/> </beans>
applicationContext.xml:注意与springMVC的父子容器关系
0.配置包扫描(除了springMVC已经存在的contrller都进行扫描)
1.数据源
2.与Mybatis的整合(全局配置文件引入,mapper配置文件引入,mapper接口实现扫描加入IOC容器等)
3.事务控制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- spring的配置文件,处理一些业务逻辑 --> <!-- 配置包扫描 --> <context:component-scan base-package="cn.crud"> <!-- 不扫描controller组件,其他都扫描 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- ==========数据源配置 ================--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driver}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- ===========配置和mybatis的整合=========== --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置mybatis全局配置文件 --> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"></property> <!-- 配置mapper文件位置 --> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean> <!-- 配置包扫描,将mapper接口实现加入IOC容器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 扫描所有dao接口的实现 --> <property name="basePackage" value="cn.crud.dao"></property> </bean> <!-- ==============事务控制的配置=============== --> <!-- 配置事务管理器:管理数据源的bean --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源的开启关闭回滚 --> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 开启基于注解的事务,必要的都使用配置实现 --> <aop:config> <!-- 配置切入点,在service层控制事务,..表示即使有子包也可以扫描 --> <aop:pointcut expression="execution(* cn.crud.service..*(..))" id="txPoint"/> <!-- 配置 事务增强--> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/> </aop:config> <!-- transaction-manager默认值即为 transactionManager,所以可以不配--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 所有方法都是事务 --> <tx:method name="*"/> <!-- 所有get开头的方法都是可读的事务 --> <tx:method name="get*" read-only="true"/> </tx:attributes> </tx:advice> </beans>
//其中,只读事务的配置为优化配置,详情见网友博客分析:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
但是你非要在“只读事务”里面修改数据,也并非不可以,只不过对于数据一致性的保护不像“读写事务”那样保险而已。
因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可
mybatis-config.xml
可以到github的网址上找到Mybatis,然后进入其官方文档,get started找到需要的东西
1.开启驼峰式命名
2.开启别名设置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!-- 开启驼峰命名规则,详细请参见官方文档 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <typeAliases> <!-- 为类起别名 --> <package name="cn.crud.bean"/> </typeAliases> </configuration>
//事务、数据源等配置都交给spring来配置了,mybatis核心配置文件需要配置的内容较少
mapper
首先通过maven引入MBG的依赖:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.5</version> </dependency>
配置文件可以参考官方的配置文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" /> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver" connectionURL="jdbc:db2:TEST" userId="db2admin" password="db2admin"> </jdbcConnection> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <javaModelGenerator targetPackage="test.model" targetProject="\MBGTestProject\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <sqlMapGenerator targetPackage="test.xml" targetProject="\MBGTestProject\src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetProject="\MBGTestProject\src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <property name="useActualColumnNames" value="true"/> <generatedKey column="ID" sqlStatement="DB2" identity="true" /> <columnOverride column="DATE_FIELD" property="startDate" /> <ignoreColumn column="FRED" /> <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> </table> </context> </generatorConfiguration>
//其中第一行需要删除需要引入的文件需要删除掉
<classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />
配置好后可以从官网文档的配置处,配置不生成注释(太多的我们不需要的注释)
从官方文档参考相关注释后,我们得出相关的逆向工程配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 配置不生产注释 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 配置数据库连接信息 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/ssm_crud" userId="root" password="root"> </jdbcConnection> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- 指定javaBean生成的 位置 --> <javaModelGenerator targetPackage="cn.crud.bean" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- 指定SQL映射文件的生成位置 --> <sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 指定dao接口生成位置,即为mapper接口的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.crud.dao" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 指定每 表的生成策略 --> <table tableName="t_emp" domainObjectName="Employee" ></table> <table tableName="t_dept" domainObjectName="Department" ></table> </context> </generatorConfiguration>
通过文档的
- From another Java program with an XML configuration
我们得到逆向工程的生成代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.crud.tests; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; public class MBGTest { public static void main(String[] args) throws Exception { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("mbg.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }
当然,逆向工程的生成代码不能100%符合我们的要求,我们对它进行适当改造:
由于我们需要查询员工的时候将员工的部门查询出来,而不是将ID查询出来,我们在mapper接口中新增两个方法:
List<Employee> selectByExample(EmployeeExample example);
Employee selectByPrimaryKey(Integer empId);
List<Employee> selectByExampleWithDept(EmployeeExample example);
Employee selectByPrimaryKeyWithDept(Integer empId);
//对比前面两个方法,后两个为我们新增的方法
这样,我们对实体类Employee进行改造,新增部门字段,完成部门名的查询条件:
private Department department;
//注意生成set/get方法
改造完成后的配置文件与接口文件如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="cn.crud.dao.EmployeeMapper"> <resultMap id="BaseResultMap" type="cn.crud.bean.Employee"> <id column="emp_id" jdbcType="INTEGER" property="empId" /> <result column="emp_name" jdbcType="VARCHAR" property="empName" /> <result column="gender" jdbcType="CHAR" property="gender" /> <result column="email" jdbcType="VARCHAR" property="email" /> <result column="d_id" jdbcType="INTEGER" property="dId" /> </resultMap> <resultMap id="WithDeptResultMap" type="cn.crud.bean.Employee"> <id column="emp_id" jdbcType="INTEGER" property="empId" /> <result column="emp_name" jdbcType="VARCHAR" property="empName" /> <result column="gender" jdbcType="CHAR" property="gender" /> <result column="email" jdbcType="VARCHAR" property="email" /> <result column="d_id" jdbcType="INTEGER" property="dId" /> <!-- 关联一个部门,使用association --> <association property="department" javaType="cn.crud.bean.Employee"> <id column="dept_id" jdbcType="INTEGER" property="deptId" /> <result column="dept_name" jdbcType="VARCHAR" property="deptName" /> </association> </resultMap> <sql id="Example_Where_Clause"> <where> <foreach collection="oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Update_By_Example_Where_Clause"> <where> <foreach collection="example.oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Base_Column_List"> emp_id, emp_name, gender, email, d_id </sql> <sql id="WithDept_Column_List"> e.emp_id, e.emp_name, e.gender, e.email, e.d_id,d.dept_id, d.dept_name </sql> <select id="selectByExample" parameterType="cn.crud.bean.EmployeeExample" resultMap="BaseResultMap"> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> from t_emp <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> </select> <!-- 增新带部门查询的sql --> <select id="selectByExampleWithDept" parameterType="cn.crud.bean.EmployeeExample" resultMap="WithDeptResultMap"> select <if test="distinct"> distinct </if> <include refid="WithDept_Column_List" /> from t_emp e LEFT JOIN t_dept d ON e.d_id=d.dept_id <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> </select> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select <include refid="WithDept_Column_List" /> from t_emp e LEFT JOIN t_dept d ON e.d_id=d.dept_id where e.emp_id = #{empId,jdbcType=INTEGER} </select> <!-- 新增带部门的按ID查询 --> <select id="selectByPrimaryKeyWithDept" parameterType="java.lang.Integer" resultMap="WithDeptResultMap"> select <include refid="WithDept_Column_List" /> from t_emp e LEFT JOIN t_dept d ON e.d_id=d.dept_id where emp_id = #{empId,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from t_emp where emp_id = #{empId,jdbcType=INTEGER} </delete> <delete id="deleteByExample" parameterType="cn.crud.bean.EmployeeExample"> delete from t_emp <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </delete> <insert id="insert" parameterType="cn.crud.bean.Employee"> insert into t_emp (emp_id, emp_name, gender, email, d_id) values (#{empId,jdbcType=INTEGER}, #{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR}, #{email,jdbcType=VARCHAR}, #{dId,jdbcType=INTEGER}) </insert> <insert id="insertSelective" parameterType="cn.crud.bean.Employee"> insert into t_emp <trim prefix="(" suffix=")" suffixOverrides=","> <if test="empId != null"> emp_id, </if> <if test="empName != null"> emp_name, </if> <if test="gender != null"> gender, </if> <if test="email != null"> email, </if> <if test="dId != null"> d_id, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="empId != null"> #{empId,jdbcType=INTEGER}, </if> <if test="empName != null"> #{empName,jdbcType=VARCHAR}, </if> <if test="gender != null"> #{gender,jdbcType=CHAR}, </if> <if test="email != null"> #{email,jdbcType=VARCHAR}, </if> <if test="dId != null"> #{dId,jdbcType=INTEGER}, </if> </trim> </insert> <select id="countByExample" parameterType="cn.crud.bean.EmployeeExample" resultType="java.lang.Long"> select count(*) from t_emp <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </select> <update id="updateByExampleSelective" parameterType="map"> update t_emp <set> <if test="record.empId != null"> emp_id = #{record.empId,jdbcType=INTEGER}, </if> <if test="record.empName != null"> emp_name = #{record.empName,jdbcType=VARCHAR}, </if> <if test="record.gender != null"> gender = #{record.gender,jdbcType=CHAR}, </if> <if test="record.email != null"> email = #{record.email,jdbcType=VARCHAR}, </if> <if test="record.dId != null"> d_id = #{record.dId,jdbcType=INTEGER}, </if> </set> <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByExample" parameterType="map"> update t_emp set emp_id = #{record.empId,jdbcType=INTEGER}, emp_name = #{record.empName,jdbcType=VARCHAR}, gender = #{record.gender,jdbcType=CHAR}, email = #{record.email,jdbcType=VARCHAR}, d_id = #{record.dId,jdbcType=INTEGER} <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByPrimaryKeySelective" parameterType="cn.crud.bean.Employee"> update t_emp <set> <if test="empName != null"> emp_name = #{empName,jdbcType=VARCHAR}, </if> <if test="gender != null"> gender = #{gender,jdbcType=CHAR}, </if> <if test="email != null"> email = #{email,jdbcType=VARCHAR}, </if> <if test="dId != null"> d_id = #{dId,jdbcType=INTEGER}, </if> </set> where emp_id = #{empId,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="cn.crud.bean.Employee"> update t_emp set emp_name = #{empName,jdbcType=VARCHAR}, gender = #{gender,jdbcType=CHAR}, email = #{email,jdbcType=VARCHAR}, d_id = #{dId,jdbcType=INTEGER} where emp_id = #{empId,jdbcType=INTEGER} </update> </mapper>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.crud.dao; import cn.crud.bean.Employee; import cn.crud.bean.EmployeeExample; import java.util.List; import org.apache.ibatis.annotations.Param; public interface EmployeeMapper { long countByExample(EmployeeExample example); int deleteByExample(EmployeeExample example); int deleteByPrimaryKey(Integer empId); int insert(Employee record); int insertSelective(Employee record); List<Employee> selectByExample(EmployeeExample example); Employee selectByPrimaryKey(Integer empId); List<Employee> selectByExampleWithDept(EmployeeExample example); Employee selectByPrimaryKeyWithDept(Integer empId); int updateByExampleSelective(@Param("record") Employee record, @Param("example") EmployeeExample example); int updateByExample(@Param("record") Employee record, @Param("example") EmployeeExample example); int updateByPrimaryKeySelective(Employee record); int updateByPrimaryKey(Employee record); }
三、单元测试
这里我们使用spring的单元测试进行测试,避免了传统的获取IOC容器等操作
引入相关的依赖:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
<scope>test</scope>
</dependency>
这里我们执行spring的单元测试,详细步骤见注释:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.crud.tests; import java.util.UUID; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import cn.crud.bean.Department; import cn.crud.bean.Employee; import cn.crud.dao.DepartmentMapper; import cn.crud.dao.EmployeeMapper; /** * 测试dao层的环境 * @author Administrator *1.使用@ContextConfiguration指定配置文件路径 *2.使用@Runwith指定单元测试使用spring的单元测试 *3.可以像原生开发一样直接注入 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:applicationContext.xml"}) public class MapperTest { @Autowired private DepartmentMapper departmentMapper; @Autowired private EmployeeMapper employeeMapper; @Autowired private SqlSession sqlSession; /** * 测试dept表的Mapper */ @Test public void TestDao(){ // 部门插入 // departmentMapper.insertSelective(new Department(null,"宣传部")); // departmentMapper.insertSelective(new Department(null,"测试部")); // 员工插入 // employeeMapper.insertSelective(new Employee(null,"Alan","M","1001@qq.com",1)); // employeeMapper.insertSelective(new Employee(null,"Bob","F","1002@qq.com",2)); //通过此方法得到的mapper可以批量操作 EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); for(int i = 0; i<500; i++){ String gender = i%2==0?"M":"F"; String uid = UUID.randomUUID().toString().substring(0, 5); mapper.insertSelective(new Employee(null, uid, gender, uid+"@qq.com", 1)); } System.out.println("批量完成"); } }
执行批处理参阅:http://blog.csdn.net/baidu_25310663/article/details/45243683
至此,环境搭建完成!