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个文件。

 

posted @ 2019-02-22 20:14  小菜鸡哒  阅读(91)  评论(0)    收藏  举报