SSM————Mybitis(2)
一、输入输出映射
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
1、环境准备
(1)复制昨天的工程,按照下图进行

(2)下图粘贴,并更名

(3)只保留Mapper接口开发相关的文件,其他删除
最终效果图:

(4)如下图修改SqlMapConfig.xml配置文件。Mapper映射器只保留包扫描的方式

2、parameterType(输入类型)
(1)传递简单类型
参考第一天的内容
使用#{}占位符,或者${}进行sql拼接
(2)传递pojo包装对象
开发中通过可以使用pojo传递查询条件。查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
包装对象:Pojo类中的一个属性是另外一个pojo。
需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
(3)编写QuryVo
1 public class QueryVo { 2 // 包含其他的pojo 3 private User user; 4 5 public User getUser() { 6 return user; 7 } 8 public void setUser(User user) { 9 this.user = user; 10 } 11 }
(4)SQL语句
SELECT * FROM user WHERE username LIKE '%张%
(5)Mapper.xml文件
在UserMapper.xml中配置sql,如图所示:

(6)Mapper接口
在UserMapper接口中添加方法,如图所示:

(7)测试方法
在UserMapperTest增加测试方法,如下:
1 @Test 2 public void testQueryUserByQueryVo() { 3 // mybatis和spring整合,整合之后,交给spring管理 4 SqlSession sqlSession = this.sqlSessionFactory.openSession(); 5 // 创建Mapper接口的动态代理对象,整合之后,交给spring管理 6 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 7 8 // 使用userMapper执行查询,使用包装对象 9 QueryVo queryVo = new QueryVo(); 10 // 设置user条件 11 User user = new User(); 12 user.setUsername("张"); 13 // 设置到包装对象中 14 queryVo.setUser(user); 15 16 // 执行查询 17 List<User> list = userMapper.queryUserByQueryVo(queryVo); 18 for (User u : list) { 19 System.out.println(u); 20 } 21 22 // mybatis和spring整合,整合之后,交给spring管理 23 sqlSession.close(); 24 }
(8)效果
测试效果图:

3、resultType(输出类型)
(1)输出简单类型
需求:查询用户表数据条数
sql:SELECT count(*) FROM `user`
【1】Mapper.xml文件
在UserMapper.xml中配置sql,如图所示:

【2】Mapper接口
在UserMapper添加方法,如图所示:

【3】测试方法
在UserMapperTest增加测试方法,如图所示:
1 @Test 2 public void testQueryUserCount() { 3 // mybatis和spring整合,整合之后,交给spring管理 4 SqlSession sqlSession = this.sqlSessionFactory.openSession(); 5 // 创建Mapper接口的动态代理对象,整合之后,交给spring管理 6 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 7 8 // 使用userMapper执行查询用户数据条数 9 int count = userMapper.queryUserCount(); 10 System.out.println(count); 11 12 // mybatis和spring整合,整合之后,交给spring管理 13 sqlSession.close(); 14 }
【4】效果

注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
(2)输出pojo对象
参考第一天的内容
(3)输出pojo列表
参考第一天的内容
4、resultMap
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
需求:查询订单表order的所有数据
1 sql:SELECT id, user_id, number, createtime, note FROM `order`
(1)声明pojo对象
数据库表如图:

Order对象
1 public class Order { 2 // 订单id 3 private int id; 4 // 用户id 5 private Integer userId; 6 // 订单号 7 private String number; 8 // 订单创建时间 9 private Date createtime; 10 // 备注 11 private String note; 12 get/set。。。 13 }
(2)Mapper.xml文件
创建OrderMapper.xml配置文件,如下:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,Mapper动态代理开发的时候使用,需要指定Mapper的类路径 --> 6 <mapper namespace="cn.itcast.mybatis.mapper.OrderMapper"> 7 <!-- 查询所有的订单数据 --> 8 <select id="queryOrderAll" resultType="order"> 9 SELECT id, user_id, 10 number, 11 createtime, note FROM `order` 12 </select> 13 </mapper>
(3)Mapper接口
接口编写如下:
1 public interface OrderMapper { 2 /** 3 * 查询所有订单 4 * 5 * @return 6 */ 7 List<Order> queryOrderAll(); 8 }
(4)测试方法
编写测试方法OrderMapperTest如下:
1 public class OrderMapperTest { 2 private SqlSessionFactory sqlSessionFactory; 3 4 @Before 5 public void init() throws Exception { 6 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 7 this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 8 } 9 10 @Test 11 public void testQueryAll() { 12 // 获取sqlSession 13 SqlSession sqlSession = this.sqlSessionFactory.openSession(); 14 // 获取OrderMapper 15 OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); 16 17 // 执行查询 18 List<Order> list = orderMapper.queryOrderAll(); 19 for (Order order : list) { 20 System.out.println(order); 21 } 22 } 23 }
(5)效果

发现userId为null
解决方案:使用resultMap
(6)使用resultMap
由于上边的mapper.xml中sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来。
改造OrderMapper.xml,如下:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,Mapper动态代理开发的时候使用,需要指定Mapper的类路径 --> 6 <mapper namespace="cn.itcast.mybatis.mapper.OrderMapper"> 7 8 <!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo --> 9 <!-- id:设置ResultMap的id --> 10 <resultMap type="order" id="orderResultMap"> 11 <!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id --> 12 <!-- property:主键在pojo中的属性名 --> 13 <!-- column:主键在数据库中的列名 --> 14 <id property="id" column="id" /> 15 16 <!-- 定义普通属性 --> 17 <result property="userId" column="user_id" /> 18 <result property="number" column="number" /> 19 <result property="createtime" column="createtime" /> 20 <result property="note" column="note" /> 21 </resultMap> 22 23 <!-- 查询所有的订单数据 --> 24 <select id="queryOrderAll" resultMap="orderResultMap"> 25 SELECT id, user_id, 26 number, 27 createtime, note FROM `order` 28 </select> 29 30 </mapper>
(7)效果
只需要修改Mapper.xml就可以了,再次测试结果如下:

二、动态sql
通过mybatis提供的各种标签方法实现动态拼接sql
需求:根据性别和名字查询用户
查询sql:
1 SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%张%'
1、if标签
(1)Mapper.xml文件
UserMapper.xml配置sql,如下:
1 <!-- 根据条件查询用户 --> 2 <select id="queryUserByWhere" parameterType="user" resultType="user"> 3 SELECT id, username, birthday, sex, address FROM `user` 4 WHERE sex = #{sex} AND username LIKE 5 '%${username}%' 6 </select>
(2)Mapper接口
编写Mapper接口,如图所示:

(3)测试方法
在UserMapperTest添加测试方法,如下:
1 @Test 2 public void testQueryUserByWhere() { 3 // mybatis和spring整合,整合之后,交给spring管理 4 SqlSession sqlSession = this.sqlSessionFactory.openSession(); 5 // 创建Mapper接口的动态代理对象,整合之后,交给spring管理 6 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 7 8 // 使用userMapper执行根据条件查询用户 9 User user = new User(); 10 user.setSex("1"); 11 user.setUsername("张"); 12 13 List<User> list = userMapper.queryUserByWhere(user); 14 15 for (User u : list) { 16 System.out.println(u); 17 } 18 19 // mybatis和spring整合,整合之后,交给spring管理 20 sqlSession.close(); 21 }
(4)效果

如图所示,测试ok
2、Where标签
上面的sql还有where 1=1 这样的语句,很麻烦
可以使用where标签进行改造
改造UserMapper.xml,如下:
1 <!-- 根据条件查询用户 --> 2 <select id="queryUserByWhere" parameterType="user" resultType="user"> 3 SELECT id, username, birthday, sex, address FROM `user` 4 <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 --> 5 <where> 6 <if test="sex != null"> 7 AND sex = #{sex} 8 </if> 9 <if test="username != null and username != ''"> 10 AND username LIKE 11 '%${username}%' 12 </if> 13 </where> 14 </select>
测试效果

3、Sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的id,username,birthday,sex,address提取出来,作为sql片段,如下:
1 <!-- 根据条件查询用户 --> 2 <select id="queryUserByWhere" parameterType="user" resultType="user"> 3 <!-- SELECT id, username, birthday, sex, address FROM `user` --> 4 <!-- 使用include标签加载sql片段;refid是sql片段id --> 5 SELECT <include refid="userFields" /> FROM `user` 6 <!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 --> 7 <where> 8 <if test="sex != null"> 9 AND sex = #{sex} 10 </if> 11 <if test="username != null and username != ''"> 12 AND username LIKE 13 '%${username}%' 14 </if> 15 </where> 16 </select> 17 18 <!-- 声明sql片段 --> 19 <sql id="userFields"> 20 id, username, birthday, sex, address 21 </sql>
如果使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace
例如下图:

4、foreach标签
向sql传递数组或List,mybatis使用foreach解析,如下:
根据多个id查询用户信息
查询sql:
1 SELECT * FROM user WHERE id IN (1,10,24)
(1)改造QueryVo
如下图在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法

(2)Mapper.xml文件
UserMapper.xml添加sql,如下:
1 <!-- 根据ids查询用户 --> 2 <select id="queryUserByIds" parameterType="queryVo" resultType="user"> 3 SELECT * FROM `user` 4 <where> 5 <!-- foreach标签,进行遍历 --> 6 <!-- collection:遍历的集合,这里是QueryVo的ids属性 --> 7 <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 --> 8 <!-- open:在前面添加的sql片段 --> 9 <!-- close:在结尾处添加的sql片段 --> 10 <!-- separator:指定遍历的元素之间使用的分隔符 --> 11 <foreach collection="ids" item="item" open="id IN (" close=")" 12 separator=","> 13 #{item} 14 </foreach> 15 </where> 16 </select> 17 18 测试方法如下图: 19 @Test 20 public void testQueryUserByIds() { 21 // mybatis和spring整合,整合之后,交给spring管理 22 SqlSession sqlSession = this.sqlSessionFactory.openSession(); 23 // 创建Mapper接口的动态代理对象,整合之后,交给spring管理 24 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 25 26 // 使用userMapper执行根据条件查询用户 27 QueryVo queryVo = new QueryVo(); 28 List<Integer> ids = new ArrayList<>(); 29 ids.add(1); 30 ids.add(10); 31 ids.add(24); 32 queryVo.setIds(ids); 33 34 List<User> list = userMapper.queryUserByIds(queryVo); 35 36 for (User u : list) { 37 System.out.println(u); 38 } 39 40 // mybatis和spring整合,整合之后,交给spring管理 41 sqlSession.close(); 42 }
(3)效果

三、Mybatis逆向工程
注:main函数只能运行一遍,如果不小心运行了第二遍,需要把生成的pojo包删了重新运行。
使用官方网站的Mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和Mapper映射文件
1、导入逆向工程
使用课前资料已有的逆向工程,如图:

(1)复制逆向工程到工作空间中

(2)导入逆向工程到eclipse中



2、修改配置文件
generatorConfig.xml中配置Mapper生成的详细信息,如图:

注意修改一下几点:
1、修改要生成的数据库表
2、pojo文件所在包路径
3、Mapper所在的包路径
配置文件如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE generatorConfiguration 3 PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" 4 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> 5 6 <generatorConfiguration> 7 <context id="testTables" targetRuntime="MyBatis3"> 8 <commentGenerator> 9 <!-- 是否去除自动生成的注释 true:是 : false:否 --> 10 <property name="suppressAllComments" value="true" /> 11 </commentGenerator> 12 <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> 13 <jdbcConnection driverClass="com.mysql.jdbc.Driver" 14 connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root"> 15 </jdbcConnection> 16 <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 17 userId="yycg" password="yycg"> </jdbcConnection> --> 18 19 <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 20 和 NUMERIC 类型解析为java.math.BigDecimal --> 21 <javaTypeResolver> 22 <property name="forceBigDecimals" value="false" /> 23 </javaTypeResolver> 24 25 <!-- targetProject:生成PO类的位置 --> 26 <javaModelGenerator targetPackage="cn.itcast.ssm.po" 27 targetProject=".\src"> 28 <!-- enableSubPackages:是否让schema作为包的后缀 --> 29 <property name="enableSubPackages" value="false" /> 30 <!-- 从数据库返回的值被清理前后的空格 --> 31 <property name="trimStrings" value="true" /> 32 </javaModelGenerator> 33 <!-- targetProject:mapper映射文件生成的位置 --> 34 <sqlMapGenerator targetPackage="cn.itcast.ssm.mapper" 35 targetProject=".\src"> 36 <!-- enableSubPackages:是否让schema作为包的后缀 --> 37 <property name="enableSubPackages" value="false" /> 38 </sqlMapGenerator> 39 <!-- targetPackage:mapper接口生成的位置 --> 40 <javaClientGenerator type="XMLMAPPER" 41 targetPackage="cn.itcast.ssm.mapper" targetProject=".\src"> 42 <!-- enableSubPackages:是否让schema作为包的后缀 --> 43 <property name="enableSubPackages" value="false" /> 44 </javaClientGenerator> 45 <!-- 指定数据库表 --> 46 <table schema="" tableName="user"></table> 47 <table schema="" tableName="order"></table> 48 </context> 49 </generatorConfiguration>
3、生成逆向工程代码
找到下图所示的java文件,执行工程main主函数


刷新工程,发现代码生成,如下图:

4、测试工程代码
(1)测试生成的代码到mybatis-spring工程,如下图:

(2)修改spring配置文件
在applicationContext.xml修改
1 <!-- Mapper代理的方式开发,扫描包方式配置代理 --> 2 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 3 <!-- 配置Mapper接口,如果需要加载多个包,直接写进来,中间用,分隔 --> 4 <!-- <property name="basePackage" value="cn.itcast.mybatis.mapper" /> --> 5 <property name="basePackage" value="cn.itcast.ssm.mapper" /> 6 </bean>
(3)编写测试方法:
1 public class UserMapperTest { 2 private ApplicationContext context; 3 4 @Before 5 public void setUp() throws Exception { 6 this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 7 } 8 9 @Test 10 public void testInsert() { 11 // 获取Mapper 12 UserMapper userMapper = this.context.getBean(UserMapper.class); 13 14 User user = new User(); 15 user.setUsername("曹操"); 16 user.setSex("1"); 17 user.setBirthday(new Date()); 18 user.setAddress("三国"); 19 20 userMapper.insert(user); 21 } 22 23 @Test 24 public void testSelectByExample() { 25 // 获取Mapper 26 UserMapper userMapper = this.context.getBean(UserMapper.class); 27 28 // 创建User对象扩展类,用户设置查询条件 29 UserExample example = new UserExample(); 30 example.createCriteria().andUsernameLike("%张%"); 31 32 // 查询数据 33 List<User> list = userMapper.selectByExample(example); 34 35 System.out.println(list.size()); 36 } 37 38 @Test 39 public void testSelectByPrimaryKey() { 40 // 获取Mapper 41 UserMapper userMapper = this.context.getBean(UserMapper.class); 42 43 User user = userMapper.selectByPrimaryKey(1); 44 System.out.println(user); 45 } 46 }
注意:
1、逆向工程生成的代码只能做单表查询
2、不能在生成的代码上进行扩展,因为如果数据库变更,需要重新使用逆向工程生成代码,原来编写的代码就被覆盖了。
3、一张表会生成4个文件。

浙公网安备 33010602011771号