Mybatis学习之路 第二篇

Mybatis学习之路 第二篇

  • 在第一篇入门案例的基础上,代码框架和结构都不变,我们继续学习,增加新的功能。
  • 本文涉及以下内容:
    1. 基于xml的Mybatis的CRUD操作
    2. Mybatis中实体类和数据库字段不一样的解决方法
    3. properties、typeAliases(类型别名)和mapper(映射器)的使用

1. 基于xml的Mybatis的CRUD操作
1.1 我们修改IUserDao中的内容如下:
public interface IUserDao {
    /**
     * 查询所有用户
     * @return
     */
    List<User> findAll();

    /**
     * 保存方法
     * @param user
     */
    void saveUser(User user);

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

    /**
     * 删除用户
     * @param userId
     */
    void deleteUser(Integer userId);

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

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

    /**
     * 查询总用户数
     * @return
     */
    int findTotal();

    /**
     * 根据queryVo中的条件查询用户
     * @param vo
     * @return
     */
    List<User> findUserByVo(QueryVo vo);
}

1.2 修改相应的IUserDao.xml的内容:
<?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="fang.dao.IUserDao">
    <!-- 配置查询所有-->
    <select id="findAll" resultType="fang.domain.User">
        select * from user
    </select>

    <!--保存用户-->
    <!--User中的id字段是自动插入的,配置的selectKey帮助我们插入后获取id值-->
    <!--value中的字段#{username}名称需要和传入的User对象的属性名称一样-->
    <!--使用#{username}会有占位符,防止Sql注入。而使用${username}是字符串拼接-->
    <insert id="saveUser" parameterType="fang.domain.User">
        <!-- 配置插入操作后,获取插入数据的id -->
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username, address, sex, birthday) values(#{username},#{address},#{sex},#{birthday});
    </insert>

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

    <!--删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{id};
    </delete>

    <!--根据id查询用户信息-->
    <!--因为传入的参数就一个,所以这里的uid可以随便写名称-->
    <select id="findById" parameterType="INT" resultType="fang.domain.User">
        select * from user where id = #{uid};
    </select>

    <!--根据姓名模糊查询-->
    <select id="findByName" parameterType="String" resultType="fang.domain.User">
        select * from user where username like #{name};
    <!-- select * from user where username like '%${value}%'; -->
    </select>

    <!--查询总用户数-->
    <select id="findTotal" resultType="int">
        select count(id) from user;
    </select>

    <!--根据queryVo的条件查询用户-->
    <select id="findUserByVo" parameterType="fang.domain.QueryVo" resultType="fang.domain.User">
        select * from user where username like #{user.username};
    </select>

</mapper>
  • 需要注意下面一些内容:
    • resultType是函数的返回值类型,parameterType是函数传入的参数类型
    • 不同的操作用不同的标签,常用的有select,insert,update,delete标签。
    • 根据姓名模糊查询中需要传入的参数如:%name%
    • queryVo为传入的包装类

1.3 编写QueryVo传递 pojo 包装对象
开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),
这时可以使用包装对象传递输入参数。
Pojo 类中包含 pojo。
需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。
  • 编写QueryVo如下
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

1.4 编写测试类
  • 在测试类中我们使用单元测试@Test注解
  • @Before注解是测试代码之前执行的函数
  • @After注解是测试代码执行完成之后执行的
  • 由于没有自动开启提交事务,所以保存操作会自动回滚,所以我们在@After中添加了提交事务代码
public class MybatisTest {

    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;

    @Before //用于在测试方法执行之前执行
    public void init() throws Exception {
        //1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After //用于在测试方法执行之后执行
    public void destory() throws Exception {
        sqlSession.commit();
        sqlSession.close();
        in.close();
    }
    
    /**
     * 测试查询所有操作
     */
    @Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
        for(User user: users) {
            System.out.println(user);
        }
    }

    /**
     * 测试保存操作
     */
    @Test
    public void testSave() {
        User user = new User();
        user.setUsername("mybatis last insertId");
        user.setAddress("北京");
        user.setSex("男");
        user.setBirthday(new Date());
        System.out.println(user);
        //5.执行保存方法
        userDao.saveUser(user);
        System.out.println(user);
    }

    /**
     * 测试更新操作
     */
    @Test
    public void testUpdate() {
        User user = new User();
        user.setId(50);
        user.setUsername("mybatis update");
        user.setAddress("北京");
        user.setSex("女");
        user.setBirthday(new Date());
        userDao.updateUser(user);
    }

    /**
     * 测试删除操作
     */
    @Test
    public void testDelete() {
        userDao.deleteUser(48);
    }

    /**
     * 测试根据id查询用户信息操作
     */
    @Test
    public void testFindOne() {
        User user = userDao.findById(50);
        System.out.println(user);
    }

    /**
     * 测试根据名字模糊查询用户信息操作
     */
    @Test
    public void testFindByName() {
        List<User> users = userDao.findByName("%王%");
//        List<User> users = userDao.findByName("王");
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * 测试查询总记录条数
     */
    @Test
    public void testFindTotal() {
        int count = userDao.findTotal();
        System.out.println(count);
    }

    /**
     * 测试使用QueryVo作为查询条件
     */
    @Test
    public void testFindByVo() {
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%王%");
        vo.setUser(user);
        List<User> users = userDao.findUserByVo(vo);
        for (User u : users) {
            System.out.println(u);
        }
    }
}
  • 到这里,基本的增删改查的操作就完成了

2. Mybatis部分细节详解
2.1 当数据库中的字段和我们写的实体类不一样时,怎么操作?
  • 例如我们的User类中的字段改成如下片段
    public class User implements Serializable {
        private Integer userId;      //id
        private String userName;     //username
        private Date userBirthday;   //birthday
        private String userSex;      //sex
        private String userAddress;  //address
    }
    • 我们需要将IUserDao.xml中的 #{username},#{address}等字段均改为#{userName},#{userAddress}
      例如:

      <insert id="saveUser" parameterType="fang.domain.User">
          <!-- 配置插入操作后,获取插入数据的id -->
          <!--keyProperty是属性字段,keyColumn是数据库字段-->
          <selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
              select last_insert_id();
          </selectKey>
          insert into user(username, address, sex, birthday) values(#{userName},#{userAddress},#{userSex},#{userBirthday});
      </insert>
    • 上述改完后还有查询语句只有username有数据,有数据是因为mysql不区分大小写。切记:在linux系统中是区分大小写的,有两种方式解决:

    1. 用as字段,如下:
      <!-- 配置查询所有-->
      <select id="findAll" resultType="fang.domain.User">
          select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user
      </select>
    2. 采用配置的方式:
      <!--配置查询结果的列名和实体类属性名的对应关系-->
      <resultMap id="userMap" type="fang.domain.User">
          <!--主键字段的对应-->
          <id property="userId" column="id"/>
          <!--非主键字段的对应-->
          <result property="userName" column="username"/>
          <result property="userAddress" column="address"/>
          <result property="userSex" column="sex"/>
          <result property="userBirthday" column="birthday"/>
      </resultMap>
      
      <!-- 配置查询所有-->
      <!--resultType="fang.domain.User改成resultMap-->
      <select id="findAll" resultMap="userMap">
          select * from user
      </select>

2.2 将数据库信息用properties文件保存,工程直接引用文件。
  1. 编写jdbcConfig.properties文件保存到resources目录(类路径)下

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis
    jdbc.username=root
    jdbc.password=root
  2. SqlMapConfig.xml中的内容修改如下:

    <?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">
    
    <!--mybatis的主配置文件-->
    <configuration>
        <properties resource="jdbcConfig.properties"/>
        <!--<properties url="file:///D:\IdeaProjects\JavaStudy\eesy_mybatis\src\main\resources\jdbcConfig.properties"/>-->
        <!--配置环境-->
        <environments default="mysql">
    <!--        配置mysql的环境-->
            <environment id="mysql">
    <!--            配置的事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
    <!--            配置数据源(连接池)-->
                <dataSource type="POOLED">
    <!--                配置连接数据库的4个基本信息-->
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    
    <!--    指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
        <mappers>
    <!--        <mapper resource="fang/dao/IUserDao.xml"></mapper>-->
            <package name="fang.dao"/>
        </mappers>
    </configuration>
  • 配置了properties属性,可以在标签类配置连接数据库的信息,也可以通过属性引用外部配置文件信息。
  • resource属性用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
  • 若使用的不是resource属性,而是url属性,这需要在自己目录中找到file位置

2.3 引用typeAliases(类型别名)和mapper(映射器)
  1. 在SqlMapConfig.xml中配置,配置完后就可以直接按使用别名,不用写全名了。别名不区分大小写。

    <typeAliases>
    <!-- 单个别名定义 --> 
    <!--<typeAlias alias="user" type="fang.domain.User"/>-->
    <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> 
    <package name="fang.domain"/>
    </typeAliases>
  2. 在SqlMapConfig.xml中配置mapper映射器

    <mappers>
    <!--<mapper resource="fang/dao/IUserDao.xml"></mapper>-->
        <package name="fang.dao"/>
    </mappers>

    之前有多少配置文件就需要写几个mapper,现在使用package就不用啦。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值