本章的代码建立在第四章《Java框架整合--切分配置文件》的项目代码之上,链接如下:
http://www.cnblogs.com/java-zhao/p/5118184.html
在实际开发中,我们在使用mybatis的时候,会注解与xml形式一起使用。
1、二者的使用场景
xml使用场景(3个):
- 条件不定的查询(eg.下边代码中的getAdminByConditions方法)
- 增加对象返回自增主键(eg.下边代码的insertAdminWithBackId方法)
- 在一个Mapper接口中,出现多个select查询(>=3个),且每个查询都需要写相同的返回@Results内容(这一部分内容通常很多),这样的话,为了使Mapper接口比较整洁,重复代码比较少,我们会将这些select方法的具体实现写在xml文件中,因为在xml文件的顶部我们就会配置与注解@Results异曲同工的东西。(当然,这一点如果嫌配置xml麻烦,这一点可忽略)
注意:前两条是硬性的,是注解所解决不了的,而第三条只是建议。
除了以上这三条之外,其他的都使用去注解就好。
2、代码实现
基本代码不变,这只列出修改过得代码:
2.1、ssmm0-userManagement:
AdminController
1 package com.xxx.web.admin; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Controller; 7 import org.springframework.web.bind.annotation.RequestMapping; 8 import org.springframework.web.bind.annotation.RequestParam; 9 import org.springframework.web.bind.annotation.ResponseBody; 10 import org.springframework.web.servlet.ModelAndView; 11 12 import com.xxx.model.userManagement.Admin; 13 import com.xxx.service.userManagement.AdminService; 14 15 /** 16 * adminController 17 */ 18 @Controller 19 @RequestMapping("/admin") 20 public class AdminController { 21 22 @Autowired 23 private AdminService adminService; 24 25 /** 26 * 管理员注册 27 */ 28 @ResponseBody 29 @RequestMapping("/register") 30 public boolean register(@RequestParam("username") String username, 31 @RequestParam("password") String password){ 32 Admin admin = new Admin(); 33 admin.setUsername(username); 34 admin.setPassword(password); 35 36 boolean isRegisterSuccess = adminService.register(admin); 37 38 return isRegisterSuccess; 39 } 40 41 /** 42 * 管理员登录 43 */ 44 @RequestMapping("/login") 45 public ModelAndView login(@RequestParam("username") String username, 46 @RequestParam("password") String password){ 47 Admin admin = adminService.login(username, password); 48 49 ModelAndView modelAndView = new ModelAndView(); 50 if(admin == null){ 51 modelAndView.addObject("message", "用户不存在或者密码错误!请重新输入"); 52 modelAndView.setViewName("error"); 53 }else{ 54 modelAndView.addObject("admin", admin); 55 modelAndView.setViewName("userinfo"); 56 } 57 58 return modelAndView; 59 } 60 61 /*****************************mybatis xml方式解决的问题*******************************/ 62 /** 63 * 根据username或password查找List<Admin> 64 */ 65 @ResponseBody 66 @RequestMapping("/findAdmin") 67 public List<Admin> findAdmin(@RequestParam(value="username",required=false) String username, 68 @RequestParam(value="password",required=false) String password, 69 @RequestParam("start") int start, 70 @RequestParam("limit") int limit){ 71 List<Admin> adminList = adminService.findAdmin(username, password, start, limit); 72 return adminList; 73 } 74 75 /** 76 * 插入一个用户并返回主键 77 * 注意:get请求也会自动装配(即将前台传入的username和password传入admin) 78 */ 79 @ResponseBody 80 @RequestMapping("/insert") 81 public Admin insertAdminWithBackId(Admin admin){ 82 return adminService.insertAdminWithBackId(admin); 83 } 84 }
说明:在这里增加了两个方法,具体看代码与注释
注:
- springMVC通过get方式传递的属性值username、password也能自动装配到对象admin中
2.2、ssmm0-data:
AdminService
1 package com.xxx.service.userManagement; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Service; 7 8 import com.xxx.dao.userManagement.AdminDao; 9 import com.xxx.model.userManagement.Admin; 10 11 /** 12 * 管理员service 13 */ 14 @Service 15 public class AdminService { 16 @Autowired 17 private AdminDao adminDao; 18 19 public boolean register(Admin admin){ 20 return adminDao.register(admin); 21 } 22 23 public Admin login(String username, String password) { 24 return adminDao.login(username, password); 25 } 26 27 /***********以下方法是为了测试mybatis中使用xml**********/ 28 public List<Admin> findAdmin(String username, String password, int start, int limit){ 29 return adminDao.findAdmin(username, password, start, limit); 30 } 31 32 public Admin insertAdminWithBackId(Admin admin){ 33 int record = adminDao.insertAdminWithBackId(admin); 34 if(record==1){ 35 return admin;//这时的admin已经被赋予主键了 36 } 37 return null; 38 } 39 }
AdminDao
1 package com.xxx.dao.userManagement; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Repository; 7 8 import com.xxx.mapper.userManagement.AdminMapper; 9 import com.xxx.model.userManagement.Admin; 10 11 /** 12 * 管理员DAO 13 */ 14 @Repository 15 public class AdminDao { 16 @Autowired 17 private AdminMapper adminMapper; 18 19 public boolean register(Admin admin){ 20 return adminMapper.insertAdmin(admin)==1?true:false; 21 } 22 23 public Admin login(String username ,String password){ 24 return adminMapper.selectAdmin(username, password); 25 } 26 27 public List<Admin> findAdmin(String username, String password, int start, int limit){ 28 return adminMapper.getAdminByConditions(username, password, start, limit); 29 } 30 31 public int insertAdminWithBackId(Admin admin){ 32 return adminMapper.insertAdminWithBackId(admin); 33 } 34 }
AdminMapper
1 package com.xxx.mapper.userManagement; 2 3 import java.util.List; 4 5 import org.apache.ibatis.annotations.Insert; 6 import org.apache.ibatis.annotations.Param; 7 import org.apache.ibatis.annotations.Result; 8 import org.apache.ibatis.annotations.Results; 9 import org.apache.ibatis.annotations.Select; 10 11 import com.xxx.model.userManagement.Admin; 12 13 /** 14 * 管理员Mapper 15 */ 16 public interface AdminMapper { 17 18 /**************注解**************/ 19 @Insert("INSERT INTO userinfo(username, password) VALUES(#{username},#{password})") 20 public int insertAdmin(Admin admin); 21 22 @Select("SELECT * FROM userinfo WHERE username = #{username} AND password = #{password}") 23 @Results(value = { 24 @Result(id = true, column = "id", property = "id"), 25 @Result(column = "username", property = "username"), 26 @Result(column = "password", property = "password") }) 27 public Admin selectAdmin(@Param("username") String username, 28 @Param("password") String password); 29 30 /***************xml**************/ 31 /** 32 * 条件不定式查询 33 * 我们这里使用@Param指定参数,这样的话,在AdminMapper.xml中就不用再使用parameterType属性了;否则得写parameterType属性 34 */ 35 public List<Admin> getAdminByConditions(@Param("username")String username, 36 @Param("password")String password, 37 @Param("start")int start, 38 @Param("limit")int limit); 39 40 /** 41 * 返回主键 42 */ 43 public int insertAdminWithBackId(Admin admin); 44 }
注意:在用xml传参的时候,
- 如果你直接传参,eg.insertAdminWithBackId(Admin admin),则在xml中的insertAdminWithBackId方法处要添加parameterType;
- 如果你用了注解传参的话,eg.getAdminByConditions(@Param("username")String username),则在xml中的getAdminByConditions方法处不用添加parameterType,当然,注解传参的时候,不能传引用类型,一般只传基本类型,eg.insertAdminWithBackId(@Param("admin")Admin admin)就是不行的
接口定义好之后,需要添加两个配置文件+修改两个配置文件。目录结构如下:
AdminMapper.xml(该xml的名字最好与对应接口的接口名完全相同)
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 4 <!-- 指定工作空间,要与接口名相同,源代码没有去看,猜测应该是通过"这里的namespace.下边方法的id"来定位方法的 --> 5 <mapper namespace="com.xxx.mapper.userManagement.AdminMapper"> 6 <!-- 指定字段映射 --> 7 <resultMap type="Admin" id="adminResultMap"> 8 <id property="id" column="id" jdbcType="INTEGER" /> 9 <result property="username" column="username" jdbcType="VARCHAR" /> 10 <result property="password" column="password" jdbcType="VARCHAR" /> 11 </resultMap> 12 13 <select id="getAdminByConditions" resultMap="adminResultMap"><!-- 返回结果为上边指定的adminResultMap --> 14 <![CDATA[ SELECT * FROM userinfo WHERE 1=1 ]]> 15 <if test="username != null"><![CDATA[ AND username = #{username} ]]></if> 16 <if test="password != null"><![CDATA[ AND password = #{password} ]]></if> 17 <![CDATA[ ORDER BY id ASC LIMIT #{start}, #{limit} ]]> 18 </select> 19 20 <!-- 若不需要自动返回主键,将useGeneratedKeys="true" keyProperty="id"去掉即可 --> 21 <insert id="insertAdminWithBackId" parameterType="Admin" useGeneratedKeys="true" keyProperty="id"> 22 <![CDATA[ 23 INSERT INTO userinfo 24 ( 25 username, 26 password 27 ) 28 VALUES 29 ( 30 #{username, jdbcType=VARCHAR}, 31 #{password, jdbcType=VARCHAR} 32 ) 33 ]]> 34 </insert> 35 36 </mapper>
注意:
- 该xml的名字最好与对应接口的接口名完全相同(eg.AdminMapper.xml对于应接口AdminMapper)
- parameterType有无参照上边对AdminMapper处所讲的注意点
- 返回自增主键有两种方法,我这里列出了最常用的也是最简单的一种
mybatis.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 6 <configuration> 7 <properties> 8 <property name="dialect" value="mysql" /> 9 </properties> 10 11 <typeAliases> 12 <!-- 这样会将com.xxx.model包及其子包下的所有类起别名为相应的简单类名 --> 13 <package name="com.xxx.model"/> 14 <!-- 如果这样去起别名的话,每一个模型类都要写一个,就比较麻烦 --> 15 <!-- <typeAlias alias="Admin" type="com.xxx.model.userManagement.Admin"/> --> 16 </typeAliases> 17 </configuration>
注意:这个文件一般用于指定属性和别名。
- 通常,属性只指定数据库方言即可;
- 有两种别名方式指定,请参照上述代码给出的注释进行选择,一般而言,都会选择package方式的
spring-data.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 6 http://www.springframework.org/schema/context 7 http://www.springframework.org/schema/context/spring-context-3.2.xsd"> 8 9 <!-- 注解扫描 --> 10 <context:component-scan base-package="com.xxx" /> 11 12 <!-- 引入数据源,这里变量的读取都是从ssmm0的pom.xml中读取的 --> 13 <bean id="xxxDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"> 14 <property name="driverClassName" value="${jdbc.driverClassName}" /> 15 <property name="url" value="${jdbc.url}" /> 16 <property name="username" value="${jdbc.username}" /> 17 <property name="password" value="${jdbc.password}" /> 18 </bean> 19 20 <!-- 引入mybatis --> 21 <bean id="xxxSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 22 <property name="dataSource" ref="xxxDataSource" /> 23 <!-- 以下两个属性是专门为xml方式配置的,若只使用注解方式,这两个属性行可以不配置 --> 24 <property name="configLocation" value="classpath:mybatis.xml"/> 25 <property name="mapperLocations"> 26 <list> 27 <value>classpath*:mapper/admin/*Mapper.xml</value> 28 </list> 29 </property> 30 </bean> 31 <bean id="xxxMapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 32 <!-- 33 这里就是包名为什么就做com.xxx.mapper.user而非com.xxx.user.mapper, 34 这样的话,比如说有两个项目com.xxx.mapper.user和com.xxx.mapper.hotel,value只需写作com.xxx.mapper即可 35 否则,value就要写作com.xxx.user.mapper,com.xxx.hotel.mapper 36 --> 37 <property name="basePackage" value="com.xxx.mapper" /> 38 <property name="sqlSessionFactoryBeanName" value="xxxSqlSessionFactory" /> 39 </bean> 40 41 </beans>
说明:只增加了两个属性配置,看代码与注释。
注:关于classpath与classpath*的具体区别自己去查,简单来说就是两句话:classpath只加载第一个找到文件;classpth*加载找到的多个文件。
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.xxx</groupId> 8 <artifactId>ssmm0</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <name>ssmm0</name> 12 <packaging>pom</packaging><!-- 父模块 --> 13 14 <!-- 管理子模块 --> 15 <modules> 16 <module>userManagement</module><!-- 具体业务1-人员管理系统 --> 17 <module>data</module><!-- 封装数据操作 --> 18 </modules> 19 20 <properties> 21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 23 </properties> 24 25 <!-- dependencyManagement不会引入实际的依赖,只是作为一个依赖池,供其和其子类使用 --> 26 <dependencyManagement> 27 <dependencies> 28 <!-- json --> 29 <dependency> 30 <groupId>com.alibaba</groupId> 31 <artifactId>fastjson</artifactId> 32 <version>1.1.39</version> 33 </dependency> 34 <!-- servlet --> 35 <dependency> 36 <groupId>javax.servlet</groupId> 37 <artifactId>javax.servlet-api</artifactId> 38 <version>3.0.1</version> 39 <scope>provided</scope> 40 </dependency> 41 <!-- spring --> 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-core</artifactId> 45 <version>3.2.6.RELEASE</version> 46 </dependency> 47 <dependency> 48 <groupId>org.springframework</groupId> 49 <artifactId>spring-beans</artifactId> 50 <version>3.2.6.RELEASE</version> 51 </dependency> 52 <dependency> 53 <groupId>org.springframework</groupId> 54 <artifactId>spring-context</artifactId> 55 <version>3.2.6.RELEASE</version> 56 </dependency> 57 <dependency> 58 <groupId>org.springframework</groupId> 59 <artifactId>spring-web</artifactId> 60 <version>3.2.6.RELEASE</version> 61 </dependency> 62 <dependency> 63 <groupId>org.springframework</groupId> 64 <artifactId>spring-webmvc</artifactId> 65 <version>3.2.6.RELEASE</version> 66 </dependency> 67 <!-- 这个是使用velocity的必备包 --> 68 <dependency> 69 <groupId>org.springframework</groupId> 70 <artifactId>spring-context-support</artifactId> 71 <version>3.2.6.RELEASE</version> 72 </dependency> 73 <!-- mysql --> 74 <dependency> 75 <groupId>mysql</groupId> 76 <artifactId>mysql-connector-java</artifactId> 77 <version>5.1.27</version> 78 <scope>runtime</scope> 79 </dependency> 80 <!-- 数据源 --> 81 <dependency> 82 <groupId>org.apache.tomcat</groupId> 83 <artifactId>tomcat-jdbc</artifactId> 84 <version>7.0.47</version> 85 </dependency> 86 <!-- mybatis --> 87 <dependency> 88 <groupId>org.mybatis</groupId> 89 <artifactId>mybatis</artifactId> 90 <version>3.1.1</version> 91 </dependency> 92 <dependency> 93 <groupId>org.mybatis</groupId> 94 <artifactId>mybatis-spring</artifactId> 95 <version>1.1.1</version> 96 </dependency> 97 <!-- velocity --> 98 <dependency> 99 <groupId>org.apache.velocity</groupId> 100 <artifactId>velocity</artifactId> 101 <version>1.5</version> 102 </dependency> 103 <dependency> 104 <groupId>velocity-tools</groupId> 105 <artifactId>velocity-tools-generic</artifactId> 106 <version>1.2</version> 107 </dependency> 108 <!-- 用于加解密 --> 109 <dependency> 110 <groupId>commons-codec</groupId> 111 <artifactId>commons-codec</artifactId> 112 <version>1.7</version> 113 </dependency> 114 <dependency> 115 <groupId>org.bouncycastle</groupId> 116 <artifactId>bcprov-jdk15on</artifactId> 117 <version>1.47</version> 118 </dependency> 119 <!-- 集合工具类 --> 120 <dependency> 121 <groupId>org.apache.commons</groupId> 122 <artifactId>commons-collections4</artifactId> 123 <version>4.0</version> 124 </dependency> 125 <!-- http --> 126 <dependency> 127 <groupId>org.apache.httpcomponents</groupId> 128 <artifactId>httpclient</artifactId> 129 <version>4.2.6</version> 130 </dependency> 131 </dependencies> 132 </dependencyManagement> 133 134 <!-- 引入实际依赖 --> 135 <dependencies> 136 <!-- json --> 137 <dependency> 138 <groupId>com.alibaba</groupId> 139 <artifactId>fastjson</artifactId> 140 </dependency> 141 <!-- spring --> 142 <dependency> 143 <groupId>org.springframework</groupId> 144 <artifactId>spring-core</artifactId> 145 </dependency> 146 <dependency> 147 <groupId>org.springframework</groupId> 148 <artifactId>spring-beans</artifactId> 149 </dependency> 150 <dependency> 151 <groupId>org.springframework</groupId> 152 <artifactId>spring-context</artifactId> 153 </dependency> 154 <!-- 集合工具类 --> 155 <dependency> 156 <groupId>org.apache.commons</groupId> 157 <artifactId>commons-collections4</artifactId> 158 </dependency> 159 </dependencies> 160 161 <build> 162 <resources> 163 <!-- 这里配置了这一块儿true,才可以让指定文件(这里是src/main/resources/spring-data.xml)读到pom.xml中的配置信息 164 , 值得注意的是,如果src/main/resources下还有其他文件,而你不想让其读pom.xml, 你还必须得把src/main/resources下的其余文件再配置一遍,配置为false(不可读pom.xml), 165 如下边的注释那样,否则,会报这些文件(在这里,就是*.properties)找不到的错误 166 --> 167 <resource> 168 <directory>src/main/resources</directory> 169 <filtering>true</filtering> 170 <includes> 171 <include>*.xml</include> 172 </includes> 173 </resource> 174 <!-- 175 <resource> 176 <directory>src/main/resources</directory> 177 <filtering>false</filtering> 178 <includes> 179 <include>*.properties</include> 180 </includes> 181 </resource> 182 --> 183 <resource> 184 <directory>src/main/resources</directory> 185 <filtering>false</filtering> 186 <includes> 187 <!-- 这里如果不加这一条,那么在spring-data.xml中配置的xml将找不到classpath:mapper/admin/AdminMapper.xml --> 188 <include>mapper/**/*.xml</include> 189 </includes> 190 </resource> 191 </resources> 192 </build> 193 194 <!-- 195 profiles可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果 196 注意两点: 197 1)<activeByDefault>true</activeByDefault>这种情况表示服务器启动的时候就采用这一套env(在这里,就是prod) 198 2)当我们启动服务器后,想采用开发模式,需切换maven的env为dev,如果env的配置本身就是dev,需要将env换成rc或prod,点击apply,然后再将env切换成dev,点击apply才行 199 --> 200 <profiles> 201 <!-- 开发env --> 202 <profile> 203 <id>dev</id> 204 <activation> 205 <activeByDefault>false</activeByDefault> 206 <property> 207 <name>env</name> 208 <value>dev</value> 209 </property> 210 </activation> 211 <properties> 212 <env>dev</env> 213 214 <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName> 215 <!-- 216 对于jdbc.url中内容的配置,如果需要配置 &时,有两种方法: 217 1)如下边这样,使用<![CDATA[XXX]]>包起来 218 2)使用jdbc.properties文件来读取此pom.xml,然后spring.xml再读取jdbc.properties文件 显然,前者更方便,而且还省了一个jdbc.properties的文件,但是,有的时候,还是会用后者的; 219 在使用后者的时候,注意三点: 220 1)需要修改上边的build中的内容 221 2)需要在spring.xml中配置<context:property-placeholder location="classpath:jdbc.properties"/> 222 3)将jdbc.properties放在ssmm0-data项目中,之后需要将ssmm0-data项目的env配置为dev 223 --> 224 <jdbc.url><![CDATA[jdbc:mysql://127.0.0.1:3306/blog?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8]]></jdbc.url> 225 <jdbc.username>root</jdbc.username> 226 <jdbc.password>123456</jdbc.password> 227 </properties> 228 </profile> 229 <!-- 预上线env --> 230 <profile> 231 <id>rc</id> 232 <activation> 233 <activeByDefault>false</activeByDefault> 234 <property> 235 <name>env</name> 236 <value>rc</value> 237 </property> 238 </activation> 239 <properties> 240 <env>rc</env> 241 242 <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName> 243 <!-- 假设的一个地址 --> 244 <jdbc.url><![CDATA[jdbc:mysql://10.10.10.100:3306/blog?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8]]></jdbc.url> 245 <jdbc.username>root2</jdbc.username> 246 <jdbc.password>1234562</jdbc.password> 247 </properties> 248 </profile> 249 <!-- 线上env --> 250 <profile> 251 <id>prod</id> 252 <activation> 253 <activeByDefault>true</activeByDefault> 254 <property> 255 <name>env</name> 256 <value>prod</value> 257 </property> 258 </activation> 259 <properties> 260 <env>prod</env> 261 262 <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName> 263 <!-- 假设的一个地址 --> 264 <jdbc.url><![CDATA[jdbc:mysql://99.99.99.999:3307/blog?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8]]></jdbc.url> 265 <jdbc.username>sadhijhqwui</jdbc.username> 266 <jdbc.password>zxczkchwihcznk=</jdbc.password> 267 </properties> 268 </profile> 269 </profiles> 270 </project>
说明:只在resource部分增加了一行关于"接口.xml"的过滤配置(作用看注释)
测试:测试的具体操作见前一章。