avatar

目录
Mybatis笔记(二)

参考:【itheima】

[toc]

输入映射和输出映射

每个sql是一个statement

parameterType(输入类型)

  1. 传递简单类型

    • 参考Mybatis笔记(一)
  2. 传递pojo对象

    • ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称
  3. 传递pojo包装对象

    • 开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

    • 代码

      定义别名

      xml
      1
      2
      3
      4
      5
      6
      7
      <typeAliases>
      <!--
      使用扫描法 批量定义别名
      定义后,别名=类名,不区分大小写,单建议按java命名规则(userMapper)
      -->
      <package name="com.machine.vo" />
      </typeAliases>

      包装对象

      java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      public class QueryVo {
      private User user;

      public User getUser() {
      return user;
      }

      public void setUser(User user) {
      this.user = user;
      }
      }

      mapper接口

      java
      1
      2
      3
      4
      5
      public interface UserMapper {

      public List<User> findUserByQueryVo(QueryVo queryVo) throws Exception;

      }

      mapper映射

      xml
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <!--
      parameterType:mapper接口中方法名的输入参数:queryVo
      public List<User> findUserByQueryVo(QueryVo queryVo)
      ${user.username}: queryVo类中的属性,使用ognl表达式取值
      -->
      <select id="findUserByQueryVo" parameterType="queryVo"
      resultType="com.machine.po.User" >
      SELECT * FROM User WHERE username like '%${user.username}%'
      </select>

      测试代码

      java
      1
      2
      3
      4
      5
      6
      QueryVo queryVo = new QueryVo();
      User user = new User();
      user.setUsername("m");
      queryVo.setUser(user);

      List<User> userList = userMapper.findUserByQueryVo(queryVo);

resultType(输出类型)

  1. 输出简单类型
  2. 输出pojo对象
  3. 输出pojo列表 List<>

resultMap

  • resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

  • 如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中。

  • 代码

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <!--
    id:resultMap唯一标志
    type:最终映射的java对象
    -->
    <resultMap id="userResultMap" type="user" >
    <!--
    id:主键
    result:普通列
    column:sql列名
    property:pojo属性名字
    -->
    <id column="id_" property="id" />
    <result column="username_" property="username" />
    <result column="sex_" property="sex" />
    <result column="birthday_" property="birthday" />
    <result column="address_" property="address" />
    </resultMap>
    <!--此时查询出来的 数据库列名 和pojo名 不对应 需要用resultMap转换-->
    <select id="findUserById" parameterType="int" resultMap="userResultMap">
    select id id_ ,
    username username_ ,
    sex sex_ ,
    birthday birthday_ ,
    address address_
    from User
    where id = #{id}

    </select>

    测试代码:

    Code
    1
    User user = userMapper.findUserById(2);

动态sql

if

mapper接口

Code
1
public List<User> findUserBySexAndUsername(User user);

mapper映射

Code
1
2
3
4
5
6
7
8
9
<select id="findUserBySexAndUsername" parameterType="user" resultType="user">
select * from User where 1=1
<if test="username != null and username!=''">
and username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
</select>

测试代码

Code
1
2
3
4
5
User user = new User();
user.setUsername("m");
//user.setSex("男");
List<User> userList = userMapper.findUserBySexAndUsername(user);
System.out.println(userList);

where

Code
1
2
3
4
5
6
7
8
9
10
11
12
<!--where可以自动处理第一个and-->
<select id="findUserBySexAndUsername" parameterType="user" resultType="user">
select * from User
<where>
<if test="username != null and username!=''">
and username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
</where>
</select>

Sql片段(抽取where)

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--
1.抽取,达到sql重用的目的
2.将where条件抽取出来放入sql
3.使用include引用
-->
<sql id="query_where_user">
<if test="username != null and username!=''">
and username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
</sql>
<!--where可以自动处理第一个and-->
<select id="findUserBySexAndUsername" parameterType="user" resultType="user">
select * from User
<where>
<include refid="query_where_user"/>
</where>
</select>

foreach

  • 使用场景

    • parameterType传入参数有List
    • 需求如: select * from User where username like ‘%m%’ and id in(1,3,5)
  • 代码

    Code
    1
    2
    3
    4
    5
    6
    public class QueryVo {
    private User user;
    private List<Integer> ids;

    //setter getter
    }
    Code
    1
    2
    3
    4
    5
    public interface UserMapper {

    public List<User> findUserByQueryVo(QueryVo queryVo) throws Exception;

    }
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    <select id="findUserByQueryVo" parameterType="queryVo"
    resultType="user" >
    select * from User
    where username like '%${user.username}%'
    <foreach collection="ids" open=" and id in(" close=")" separator="," item="id">
    #{id}
    </foreach>
    </select>

    测试代码

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    QueryVo queryVo = new QueryVo();

    User user = new User();
    user.setUsername("m");
    queryVo.setUser(user);

    List<Integer> ids = new ArrayList<>();
    ids.add(1);
    ids.add(3);
    ids.add(5);
    queryVo.setIds(ids);

    List<User> userList = userMapper.findUserByQueryVo(queryVo);

关联查询

用户订单模型

一个用户可以下多个订单,一个订单只对应一个用户

一对一查询

  • 案例:查询订单信息,关联查询用户信息

  • 方法一:自动映射(定义专门的PO作为输出类型)

    sql:

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT
    orders.*,
    user.username,
    userss.address
    FROM
    orders,
    user
    WHERE orders.user_id = user.id

    po类:

    Code
    1
    2
    3
    4
    5
    6
    public class OrdersCustom extends Orders {

    //继承Orders,再添加User属性即可
    private String username;// 用户名称
    private String address;// 用户地址
    //set get

    Mapper.xml:

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- 查询所有订单信息 -->
    <select id="findOrdersList" resultType="cn.itcast.mybatis.po.OrdersCustom">
    SELECT
    orders.*,
    user.username,
    user.address
    FROM
    orders,user
    WHERE orders.user_id = user.id
    </select>

    Mapper接口:

    Code
    1
    public List<OrdersCustom> findOrdersList() throws Exception;

    测试:

    Code
    1
    List<OrdersCustom> list = userMapper.findOrdersList();
  • 方法二:手动映射(在Orders类里包含User类)

    Code
    1
    2
    3
    4
    5
    6
    public class Orders {
    private int id;
    private String createTime;
    private String state;

    private User user;
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <!-- 查询订单关联用户信息使用resultmap -->
    <resultMap type="com.machine.po.Orders" id="orderUserResultMap">
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property="note"/>
    <!--
    一对一关联映射
    association:表示进行关联查询单条记录
    -->
    <!--
    property:Orders对象的user属性
    javaType:user属性对应 的类型
    -->
    <association property="user" javaType="com.machine.po.User">
    <!--
    column:user表的主键对应的列
    property:user对象中id属性
    -->
    <id column="user_id" property="id"/>
    <result column="username" property="username"/>
    <result column="address" property="address"/>
    </association>
    </resultMap>

    <select id="findOrdersWithUserResultMap" resultMap="orderUserResultMap">
    SELECT
    o.id,
    o.user_id,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    orders o
    JOIN `user` u ON u.id = o.user_id
    </select>

一对多查询

  • 查询用户信息及 关联的订单信息

  • 代码

    pojo

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class User {

    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;

    private List<Orders> ordersList;
    //set get

    mapper.xml

    xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <resultMap id="userOrdersRM" type="user">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="sex" property="sex"/>
    <result column="birthday" property="birthday"/>
    <result column="address" property="address"/>
    <!--
    一对多映射关系
    property: User类中对应集合 属性名
    ofType:集合的类型 此处使用别名
    -->
    <collection property="ordersList" ofType="orders">
    <id column="orderId" property="id" />
    <result column="createTime" property="createTime"/>
    <result column="state" property="state"/>
    </collection>

    </resultMap>
    <select id="findUserOrders" resultMap="userOrdersRM">
    select u.* ,
    o.id orderId,
    o.create_time createTime,
    o.state
    from user u
    LEFT JOIN orders o ON u.id = o.user_id
    </select>

    接口

    Code
    1
    public List<User> findUserOrders();

    测试:

    Code
    1
    List<User> userOrdersList = userMapper.findUserOrders();

Mybatis整合Spring

整合思路

  1. SqlSessionFactory对象应该放到spring容器中作为单例存在。
  2. 传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
  3. Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
  4. 数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

整合需要的jar包

  1. spring的jar包
  2. Mybatis的jar包
  3. Spring+mybatis的整合包。
  4. Mysql的数据库驱动jar包。
  5. 数据库连接池的jar包。

整合的步骤

第一步:创建一个java工程。
第二步:导入jar包。(上面提到的jar包)
第三步:mybatis的配置文件sqlmapConfig.xml
第四步:编写Spring的配置文件
    1、数据库连接及连接池
    2、事务管理(暂时可以不配置)
    3、sqlsessionFactory对象,配置到spring容器中
    4、mapeer代理对象或者是dao实现类配置到spring容器中。
第五步:编写dao或者mapper文件
第六步:测试。

SqlMapConfig.xml

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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>
<typeAliases>
<!--扫描包,配置别名-->
<package name="com.machine.ms.po"/>
</typeAliases>
<mappers>
<mapper resource="sqlmap/userMapper.xml"/>
</mappers>
</configuration>

applicationContext.xml

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"

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.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

<!--加载配置文件-->
<context:property-placeholder location="classpath:db.properties" />
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<!--Spring管理sqlSessionFactory,使用mybatis-spring整合包-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据库连接池-->
<property name="dataSource" ref="dataSource"/>
<!--加载mybatis全局配置文件-->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>

</bean>


</beans>

db.properties

Dao的开发

传统Daok开发方式(不重要)

接口+实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类

Code
1
2
3
4
public interface UserDao {
public User getUserById(int id);
public void InsertUser(User user);
}
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {

@Override
public User getUserById(int id) {

//SqlSessionDaoSupport提供获得SqlSession的方法,
//但在配置<bean>时 要注入sqlSessionFactory
SqlSession sqlSession = super.getSqlSession();
User user = sqlSession.selectOne("user.findUserById", id);

//不要手动关闭sqlSession
//sqlSession.close();

return user;
}

@Override
public void InsertUser(User user) {
SqlSession sqlSession = super.getSqlSession();
sqlSession.insert("user.insertUser",user);

//手动事务提交不被Spring允许
//sqlSession.commit();
//但手动不要关闭SqlSession
}
}
Code
1
2
3
4
<!--传统DAO开发,需要给支持类(父类) 注入sqlSessionFactory-->
<bean id="userDao" class="com.machine.ms.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
Code
1
2
3
4
5
6
7
8
9
10
11
12
<mapper namespace="user">

<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM user where id = #{id}
</select>

<insert id="insertUser" parameterType="user" >
INSERT INTO user(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>

</mapper>
Code
1
2
3
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>

测试:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test1(){
ApplicationContext context =
new ClassPathXmlApplicationContext("spring/applicationContext.xml");
UserDao userDao = (UserDao)context.getBean("userDao");

User user = userDao.getUserById(2);

System.out.println(user);

//System.out.println("========");
//User user2 = new User();
//user2.setUsername("uuu");
//userDao.InsertUser(user);
}

Mapper代理形式开发Dao(不重要)

Code
1
2
3
4
5
<!-- 配置mapper代理对象 -->
<bean class="com.machine.ms.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.machine.ms.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

扫描包的形式配置mapper(推荐)

  • mybatis mapper开发规范:见Mybatis笔记(一)

    • namespace
    • 方法名=id名
  • 配置

    Code
    1
    2
    3
    4
    5
    6
    7
    <!--
    使用扫描包 的形式 创建mapper代理对象
    遵守规范:UserMapper.java 和UserMapper放在同一个mapper包下
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.machine.ms.mapper"/>
    </bean>

    以上配置后,不需要以下配置

    Code
    1
    2
    3
    4
    <mappers>
    <!--扫描包-->
    <package name="com.machine.ms.mapper" />
    </mappers>
  • 代码总结

    SqlMapConfig.xml

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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>
    <typeAliases>
    <!--扫描包,配置别名-->
    <package name="com.machine.ms.po"/>
    </typeAliases>

    </configuration>

    applicationContext.xml

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <?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:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"

    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.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

    <!--加载配置文件-->
    <context:property-placeholder location="classpath:db.properties" />
    <!--数据库连接池-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--Spring管理sqlSessionFactory,使用mybatis-spring整合包-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--数据库连接池-->
    <property name="dataSource" ref="dataSource"/>
    <!--加载mybatis全局配置文件-->
    <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>

    </bean>


    <!--使用扫描包 的形式 创建mapper代理对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.machine.ms.mapper"/>
    </bean>


    </beans>

    UserMapper.xml

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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="com.machine.ms.mapper.UserMapper">

    <select id="findUserById" parameterType="int" resultType="user">
    SELECT * FROM user where id = #{id}
    </select>

    <insert id="insertUser" parameterType="user" >
    INSERT INTO user(username,birthday,sex,address)
    VALUES(#{username},#{birthday},#{sex},#{address})
    </insert>

    </mapper>

    UserMapper.java

    Code
    1
    2
    3
    4
    public interface UserMapper {
    public User findUserById(int id);
    public void InsertUser(User user);
    }

    测试:

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Test
    public void test2(){
    ApplicationContext context =
    new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");

    //Spring返回mapper代理对象
    UserMapper userMapper = context.getBean(UserMapper.class);

    User user = userMapper.findUserById(2);
    System.out.println(user);

    }

Mybatis 逆向工程

文章作者: Machine
文章链接: https://machine4869.gitee.io/2018/04/20/15326651019569/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 哑舍
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论