Mybatis学习02 - 基于XML的Mybatis配置

基于XML配置的CRUD操作

查询操作

在dao层接口UserDao中定义查询方法

/**
 * 查询所有用户
 * @return
 */
 List<User> findAll();

/**
 * 根据id查询用户
 * @param id
 * @return
 */
 User findById(Integer id);

在UserDao.xml中添加配置,查询使用<select>标签

<!--查询所有-->
    <select id="findAll" resultType="com.chenpeng.domain.User">
        <!--select id as userId,username as userName,birthday as userBirthday,sex as userSex,address as userAddress from users-->
        select * from users
    </select>
<!--根据id查询用户-->
    <select id="findById" parameterType="java.lang.Integer" resultType="com.chenpeng.domain.User">
        select * from users where id=#{uid}
    </select>

其中<select>标签中的属性:

  • parameterType:表示方法的参数类型
  • resultType:表示封装结果集的实体类的全限定类名

测试方法如下

@Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
@Test
    public void testFindById(){
        User user = userDao.findById(52);
        System.out.println(user);
    }

增加操作

在dao层接口UserDao中定义增加方法

/**
 * 保存用户
 * @param user
 */
 void saveUser(User user);

在UserDao.xml中添加配置,增加使用<insert>标签

<!--保存用户-->
    <insert id="saveUser" parameterType="com.chenpeng.domain.User">
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        	<!--获取插入用户的id-->
            select last_insert_id()
        </selectKey>
        insert into users(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>

其中<selectKey>标签中的属性:

  • keyProperty:表示实体类User中的属性名
  • keyColumn:表示数据库中的字段名
  • resultType:表示查询的返回值类型
  • order:表示这条sql语句在插入之前执行还是之后执行,值有BEFORE和AFTER

测试方法如下

@Test
    public void testSaveUser(){
        User user = new User();
        user.setUsername("cy");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("潮汕");
        System.out.println("保存操作之前:"+user);
        userDao.saveUser(user);
        System.out.println("保存操作之后:"+user);
    }

更新操作

在dao层接口UserDao中定义更新方法

/**
 * 更新用户
 * @param user
 */
 void updateUser(User user);

在UserDao.xml中添加配置,更新使用<update>标签

<!--更新用户-->
    <update id="updateUser" parameterType="com.chenpeng.domain.User">
        update users set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
    </update>

测试方法如下

@Test
    public void testUpdateUser(){
        User user = new User();
        user.setId(51);
        user.setUsername("cyy");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("广东潮汕鮀浦");
        userDao.updateUser(user);
    }

删除操作

在dao层接口UserDao中定义删除方法

/**
 * 根据id删除用户
 * @param id
 */
 void deleteUser(Integer id);

在UserDao.xml中添加配置,删除使用<delete>标签

<!--删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        <!--此处大括号内只是一个占位符,命名没有要求-->
        delete from users where id=#{uid}
    </delete>

测试方法如下

@Test
    public void testDeleteUser(){
        userDao.deleteUser(51);
    }

模糊查询

在dao层接口UserDao中定义查询方法

/**
 * 根据名称模糊查询
 * @param username
 * @return
 */
 List<User> findByName(String username);

在UserDao.xml中添加配置

<!--根据名称模糊查询-->
    <select id="findByName" parameterType="String" resultType="com.chenpeng.domain.User">
    	<!--使用PreparedStatement的参数占位符,测试代码中必须加上%-->
        select * from users where username like #{username}
        <!--也可使用Statement拼接sql语句,测试代码中不用加%,但此种方式可能发生sql注入,不常用-->
        <!--select * from users where username like %${value}%-->
    </select>

测试方法如下

@Test
    public void testFindByName(){
        List<User> users = userDao.findByName("%陈%");
        for (User user : users) {
            System.out.println(user);
        }
    }

使用实体类的包装对象作为查询条件

在domain层下创建实体类QueryVo

package com.chenpeng.domain;

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

在dao层接口UserDao中定义查询方法

/**
 * 根据vo模糊查询
 * @param vo
 * @return
 */
 List<User> findByVo(QueryVo vo);

在UserDao.xml中添加配置

<!--根据vo模糊查询-->
    <select id="findByVo" parameterType="com.chenpeng.domain.QueryVo" resultType="com.chenpeng.domain.User">
    	<!--此处大括号内不能直接写username,因为QueryVo类中没有getUsername()方法,所以可以使用OGNL			表达式,使用类名.属性名的方式获取-->
        select * from users where username like #{user.username}
    </select>

测试方法如下

@Test
    public void testFindByVo(){
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%陈%");
        vo.setUser(user);
        List<User> users = userDao.findByVo(vo);
        for (User u : users) {
            System.out.println(u);
        }
    }

调整实体类属性解决属性名和数据库中字段名不对应问题

修改实体类User

package com.chenpeng.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer userId;
    private String userName;
    private Date userBirthday;
    private String userSex;
    private String userAddress;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userBirthday=" + userBirthday +
                ", userSex='" + userSex + '\'' +
                ", userAddress='" + userAddress + '\'' +
                '}';
    }
}

此时实体类中属性名和数据库中字段名不对应了,再次测试会发现封装结果集时只有username有值,其他均为null,因为Windows环境下的Mysql数据库不区分大小写(Linux环境下区分大小写)

问题解决

1.修改sql语句,例如

select id as userId,username as userName,birthday as userBirthday,sex as userSex,address as userAddress from users

但是这种方式需要修改之前写好的sql语句,非常麻烦

2.配置查询结果的列名和实体类的属性名的对应关系

在UserDao.xml中添加配置

<resultMap id="userMap" type="com.chenpeng.domain.User">
        <!--主键字段的对应-->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userBirthday" column="birthday"></result>
        <result property="userSex" column="sex"></result>
        <result property="userAddress" column="address"></result>
</resultMap>

同时修改<select>标签中的属性resultType为resultMap

<select id="findAll" resultMap="userMap">
        select * from users
</select>

这种方式不用修改sql语句,只需将resultType属性改为resultMap属性即可,更加方便

Mybatis配置文件中的其他标签的使用

properties标签

<properties>标签中配置连接数据库的信息,有两种方式配置

  1. 使用<properties>标签直接配置

    <properties>
        resource="jdbcConfig.properties"-->
            <!--<property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/user?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
            <property name="username" value="用户名"/>
            <property name="password" value="密码"/>
    </properties>
    <!--配置数据源(连接池)-->
    <dataSource type="POOLED">
         <property name="driver" value="driver"/>
         <property name="url" value="url"/>
         <property name="username" value="username"/>
         <property name="password" value="password"/>
    </dataSource>
    
  2. 使用<properties>标签中的resource属性或url属性

    resource属性用于指定配置文件的位置,按照类路径的写法来写,并且必须存在于类路径下

<properties resource="jdbcConfig.properties>


或者


修改数据源配置

```

其中jdbcConfig.properties文件在resources目录下,内容如下

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=用户名
jdbc.password=密码

typeAliases标签

<typeAliases>标签中可以为实体类配置别名,有两种方式配置

  1. 使用<typeQliases>标签为单个实体类配置别名

    <typeAliases>
    	<typeAlias type="com.chenpeng.domain.User" alias="user"></typeAlias>
    </typeAliases>
    

    其中typeAlias中的属性:

    • type:表示实体类的全限定类名
    • alias:表示实体类的别名,不区分大小写
  2. 使用<package>标签为整个包内的实体类配置别名,配置后实体类的类名就是别名,不区分大小写

    <typeAliases>
         <package name="com.chenpeng.domain"/>
    </typeAliases>
    

mappers标签

<mappers>标签中可以配置映射文件的位置,有两种方式配置

  1. 使用<mapper>标签中的resource属性指定映射文件的位置

    <mappers>
    	<mapper resource="com/chenpeng/dao/UserDao.xml"/>
    </mappers>
    
  2. 使用<package>标签指定UserDao接口所在的包,从而找到UserDao接口的映射文件

    <mappers>
        <package name="com.chenpeng.dao"/>
    </mappers>
    

动态sql语句

if标签 - 执行判断

在dao层接口UserDao中定义查询方法

/**
 * 根据条件查询
 * @param user
 * @return
 */
 List<User> findByCondition(User user);

在UserDao.xml中添加配置

<select id="findByCondition" parameterType="user" resultMap="userMap">
     select * from users where 1=1
     	<!--如果user对象的userName不为空,就加上username的判断条件-->
        <if test="userName != null">
              and username = #{userName}   
        </if>
</select>

测试方法如下

@Test
    public void testFindByCondition(){
        User user = new User();
        user.setUserName("陈宇宇宇");
        List<User> users = userDao.findByCondition(user);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

where标签 - 给sql语句加上where条件判断

上述例子中进行条件判断时加上了where 1 = 1,以防止传入的user对象为空,也可以使用<where>标签,它可以根据传入的实体类对象判断是否加上where语句

<select id="findByCondition" parameterType="user" resultMap="userMap">
        select * from users
        <where>
            <if test="userName != null">
                and username = #{userName}
            </if>
        </where>
</select>

foreach标签 - 遍历集合

当要进行聚合查询时(即in/not in查询),可以使用<foreach>标签

在dao层接口UserDao中定义查询方法

/**
 * 根据QueryVO中提供的id集合,查询用户信息
 * @param vo
 * @return
 */
 List<User> findUserInIds(QueryVo vo);

在UserDao.xml中添加配置

<!--根据id集合查询-->
    <select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
        select * from users
        <where>
            <if test="ids != null and ids.size() > 0">
            <!--item中的值跟下面#{}内的值对应-->
                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

其中<foreach>标签中的属性:

  • collection:表示要遍历的集合对象
  • open:遍历的sql以什么开头
  • close:遍历的sql以什么结束
  • separator:分隔符,遍历一次后在集合中的对象之间加的字符
  • item:表示每次遍历的元素

测试方法如下

@Test
    public void testFindUserInIds(){
        QueryVo vo = new QueryVo();
        List<Integer> list = new ArrayList<Integer>();
        list.add(52);
        list.add(53);
        list.add(56);
        list.add(57);
        list.add(58);
        list.add(59);
        vo.setIds(list);
        List<User> user = userDao.findUserInIds(vo);
        for (User user1 : user) {
            System.out.println(user1);
        }
    }

sql标签 - 抽取sql语句中的重复语句

每个方法的sql语句中,有大量重复的部分,可以使用<sql>标签定义sql语句,使用<include>标签引用<sql>标签中的sql语句

<sql id="defaultSelect">
        select * from users
</sql>
<select id="findAll" resultMap="userMap">
        <include refid="defaultSelect"/>
</select>
posted @ 2020-04-14 11:58  codeDD  阅读(101)  评论(0编辑  收藏  举报