• MyBatis学习(一)---配置文件,Mapper接口和动态SQL


    MyBatis

      MyBatis官方学习网站

             http://www.mybatis.org/mybatis-3/zh/index.html

      为什么需要MyBatis?

      Jdbc操作数据库的不足之处

    1、需要通过硬编码的方式建立到数据库的连接

    2、需要通过硬编码的方式来创建PreparedStatment对象

    3、频繁的关闭连接、建立连接,导致系统的性能会下降

      MyBatis

      MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。Mybatis框架封装了jdbc的一个持久层的框架,它和Hibernate都属于ORM框架,Hibernate是一个完全的orm框架,Mybatis不是一个完全的orm框架,不需要关注数据库连接的建立、Statement或PreparedStatement的创建,更多的去关注sql语句本身。

      通过下面的项目来了解MyBatis

      项目目录结构

    本项目使用的Oracle数据库,项目对象的表为user_tab

    src目录下是一个是MyBatis的配置文件

    <?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>
        <!-- 指定了默认的环境为development -->
      <environments default="development">
          <!-- 指出了环境的唯一标识 -->
        <environment id="development">
            <!-- 指出了事务管理器 -->
          <transactionManager type="JDBC"/>
          <!-- 指出了连接池,并指出了连接数据库的驱动,url,用户名,密码 -->
          <dataSource type="POOLED">
            <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
            <property name="username" value="scott"/>
            <property name="password" value="itcast"/>
          </dataSource>
        </environment>
      </environments>
      <!-- 注册映射文件,路径中.都用/代替 -->
      <mappers>
        <mapper resource="com/ghq/model/dao/impl/UserDaoImpl.xml"/>
      </mappers>
    </configuration>

     

    表所对应的实体类为User.java

    package com.ghq.model.entity;
    
    import java.util.Date;
    
    public class User {
        private int id;
        private String username;
        private String userpass;
        private Date birthday;
        private int height;
        private String gender;
        
        public User(int id, String username, String userpass, Date birthday,
                int height, String gender) {
            this.id = id;
            this.username = username;
            this.userpass = userpass;
            this.birthday = birthday;
            this.height = height;
            this.gender = gender;
        }
        public User(String username, String userpass, Date birthday, int height,
                String gender) {
            this.username = username;
            this.userpass = userpass;
            this.birthday = birthday;
            this.height = height;
            this.gender = gender;
        }
        public User() {
            
        }
        //省略setter/getter方法
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", userpass="
                    + userpass + ", birthday=" + birthday + ", height=" + height
                    + ", gender=" + gender + "]";
        }
        
    }

     

     工具类MyBatisDb.java

      主要的功能是获取获取SqlSessionFactory以及SqlSession的对象,SqlSession中具有对数据表增删改查的方法。

    package com.ghq.model.utils;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    public class MybatisDb {
        private static String config = "mybatis-config.xml";
        private static SqlSessionFactory sqlSessionFac;
        
        static{
            try {
                //读取配置文件
                InputStream inputstream = Resources.getResourceAsStream(config);
                //获取SqlSessionFactory对象
                sqlSessionFac = new SqlSessionFactoryBuilder().build(inputstream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        //获取SqlSession对象,并且开启了事务
        public static SqlSession getSession(){
            return sqlSessionFac.openSession();
        }
        
    }

     

     

    UserDao.java 是一个接口,其中的内容主要是实现用户的增删改查功能

    package com.ghq.model.dao;
    
    import java.util.List;
    import com.ghq.model.entity.User;
    
    public interface UserDao {
        //根据id查询用户
        User getUserById(int id);
        //根据模糊姓名和性别查询
        List<User> getUserBynameAndGender(User u);
        //新增用户
        boolean addUser(User u);
        //修改用户
        boolean updateUser(User u);
        //删除用户
        boolean delUser(int id);
    }

     

     

    UserDaoImpl.java是UserDao的实现类

    package com.ghq.model.dao.impl;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    
    import com.ghq.model.dao.UserDao;
    import com.ghq.model.entity.User;
    import com.ghq.model.utils.MybatisDb;
    
    public class UserDaoImpl implements UserDao {
        //通过id获取用户的方法
        @Override
        public User getUserById(int id) {
            //获得SQLSession对象
            SqlSession session = MybatisDb.getSession();
            //执行com.ghq.model.dao.impl.UserDaoImpl.getUserById标识的SQL语句,在执行前为占位参数赋值
            User u = session.selectOne("com.ghq.model.dao.impl.UserDaoImpl.getUserById", id);
            session.close();
            return u;
        }
    
        //根据模糊姓名和性别查询
        @Override
        public List<User> getUserBynameAndGender(User u) {
            //获得SQLSession对象
            SqlSession session = MybatisDb.getSession();
            List<User> ulist = session.selectList("com.ghq.model.dao.impl.UserDaoImpl.getUserBynameAndGender", u);
            session.close();
            return ulist;
        }
    
        //新增用户
        @Override
        public boolean addUser(User u) {
            SqlSession session = MybatisDb.getSession();
            int row = session.insert("com.ghq.model.dao.impl.UserDaoImpl.addUser", u);
            session.commit();
            session.close();
            if (row > 0) {
                return true;
            }
            return false;
        }
    
        //修改用户
        @Override
        public boolean updateUser(User u) {
            SqlSession session = MybatisDb.getSession();
            int row = session.update("com.ghq.model.dao.impl.UserDaoImpl.updateUser", u);
            session.commit();
            session.close();
            if (row > 0) {
                return true;
            }
            return false;
        }
    
        //删除用户
        @Override
        public boolean delUser(int id) {
            SqlSession session = MybatisDb.getSession();
            int row = session.delete("com.ghq.model.dao.impl.UserDaoImpl.delUser", id);
            session.commit();
            session.close();
            if (row > 0) {
                return true;
            }
            return false;
        }
    
    }

     

     

    要想实现对数据库的操作,必须配置sql的映射文件UserdaoImpl.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">
      
    <!-- namespace不允许重复,用于区分同名的SQL语句标识 -->
    <mapper namespace="com.ghq.model.dao.impl.UserDaoImpl">
        <!--  映射文件中的SQL语句没有分号
                    #{}相当于占位符? #{}中名字标识输入参数的名字,如果输入参数是简单类型,则#{}中参数名任意
                    parameterType指出了输入参数类型之外的类型
                    resultType是结果类型,即返回的记录中单条记录的类型
         -->
      <select id="getUserById" parameterType="int" resultType="com.ghq.model.entity.User">
        select * from user_tab where id = #{id}
      </select>
      <!-- 输入参数类型不是简单类型,#{}中的输入参数的名字不能任意,参数类型是自定义的实体类型,#{}中使用的是属性名,模糊查询不使用#{},而使用${}  #{}两端没有单引号 -->
      <select id="getUserBynameAndGender" parameterType="com.ghq.model.entity.User" resultType="com.ghq.model.entity.User">
        select * from user_tab where username like '%${username}%' and gender = #{gender}
      </select>
      
      <insert id="addUser" parameterType="com.ghq.model.entity.User" >
          <! -- 新增用户中,用户id是通过序列来实现自动增长,所以需在数据库中创建user_tb_seq序列,然后通过select语句查询出下一个序列值,封装到标志属性中。order指出了查询是否在新增之前,是的话为BEFORE,否则为AFTER,resultType指出了查询的数据的类型,不能省略 -->
          <selectKey keyProperty="id" order="BEFORE" resultType="int">
              select user_tb_seq.nextval from dual
          </selectKey>
          insert into user_tab (id,username,userpass,birthday,height,gender) values 
          (#{id},#{username},#{userpass},#{birthday},#{height},#{gender})
      </insert>
      
      <update id="updateUser" parameterType="com.ghq.model.entity.User">
          update user_tab set username = #{username},userpass = #{userpass},birthday = #{birthday},
          height = #{height},gender = #{gender} where id = #{id}
      </update>
      
      <delete id="delUser" parameterType="int">
          delete from user_tab where id = #{id}
      </delete>
    </mapper>

     

     

    使用JUnit4进行单元测试testmybatis.java

    package com.ghq.test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    import org.junit.Test;
    
    import com.ghq.model.dao.UserDao;
    import com.ghq.model.dao.impl.UserDaoImpl;
    import com.ghq.model.entity.User;
    
    public class testmybatis {
        @Test
        public void testgetUserbyID(){
            UserDao userdao = new UserDaoImpl();
            User u = userdao.getUserById(7);
            System.out.println(u);
        }
        
        @Test
        public void testgetUserbynameAndGender(){
            UserDao userdao = new UserDaoImpl();
            User user = new User();
            user.setUsername("张");
            user.setGender("女");
            List<User> ulist = userdao.getUserBynameAndGender(user);
            for (User uu : ulist) {
                System.out.println(uu);
            }        
        }
        
        @Test
        public void testaddUser(){
            UserDao userdao = new UserDaoImpl();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String str = "1990-12-12";
            Date d = null;
            try {
                d = dateFormat.parse(str);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            
            User user = new User("张三","zs",d,160,"女");
            boolean flag = userdao.addUser(user);
            if (flag) {
                System.out.println("插入成功");
            }else{
                System.out.println("插入失败");
            }                
        }
        
        @Test
        public void testupdateUser(){
            UserDao userdao = new UserDaoImpl();
            User user = new User(1,"李四 ","ls",new Date(),170,"男");
            boolean flag = userdao.updateUser(user);
            if (flag) {
                System.out.println("修改成功");
            }else{
                System.out.println("修改失败");
            }                
        }
        
        @Test
        public void testdelUser(){
            UserDao userdao = new UserDaoImpl();
            boolean flag = userdao.delUser(1);
            if (flag) {
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }   
        }
    }

     

     

    Mapper接口

      MyBatis的项目中,可以没有dao的实现类

      Mybatis 提供了 Mapper接口的代理对象,在执行 Mapper接口方法时,实际执行的是Mybatis的代理对象,代理对象在 invoke 方法内获取 Mapper接口类全名+方法全名 作为statement的ID,然后通过ID去Statement匹配注册的SQL,然后使用 SqlSession 执行这个 SQL。

      实现这样的功能前提是映射文件和接口主文件名相同,且在同一个包下,映射文件的命名空间是接口的全限定名。

     

    在mybatis-config.xml配置文件中

     

      1、注册映射文件时,若映射文件过多,推荐使用批量注册映射文件。

      批量注册映射文件的前提是:接口的主文件名要和相应映射文件名一致,而且映射文件中的namespace是接口的全限定名,接口和映射文件在同一个包下

    <!-- 注册映射文件(批量注册映射文件,注册com.ghq.model.dao下的所有配置文件) -->
      <mappers>
        <package name="com.ghq.model.dao"/>
      </mappers>

      2、在配置文件中定义别名,可以在映射文件中使用别名。

    <!-- 在配置文件中定义别名,可以在映射文件中使用别名 -->
        <typeAliases>
            <!-- 一次定义一个别名 -->
            <!-- <typeAlias type="com.ghq.model.entity.User" alias="user"/> -->
            <!-- 为该包下的实体类定义别名 -->
            <package name="com.ghq.model.entity"/>
        </typeAliases>

     

       定义别名后,可以在resultType或paramterType中使用user

      3、可以将连接数据库的驱动,url,用户名和密码存放在properties文件中。

    db.properties文件中的配置

    db.driver=oracle.jdbc.driver.OracleDriver
    db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
    db.username=scott
    db.password=itcast
    <!-- 加载db.properties文件 -->
    <properties resource="db.properties"></properties>
    
    <environments default="development">
         <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${db.driver}"/>
            <property name="url" value="${db.url}"/>
            <property name="username" value="${db.username}"/>
            <property name="password" value="${db.password}"/>
          </dataSource>
        </environment>
      </environments>

     

     

    以根据id查询用户为例:

    UserDao中的代码

    public interface UserDao {
        //根据id查询用户
        User getUserById(int id);
    }

    UserDao的映射文件UserDao.xml

    <mapper namespace="com.ghq.model.dao.UserDao">
      <select id="getUserById" parameterType="int" resultType="user">
        select * from user_tab where id = #{id}
      </select>
    </mapper>

    单元测试的代码

    public class testmybatis {
        @Test
        public void testgetUserbyID(){
            SqlSession session = MybatisDb.getSession();
            UserDao userdao = session.getMapper(UserDao.class);
            User u = userdao.getUserById(1);
            System.out.println(u);
        }
    }

     

     

    动态sql语句

    动态sql语句涉及的元素

             1、where

             where元素默认去除第一个and,如果参数输入不合法,则会删掉where子句

             2、if

             对输入参数进行条件判断,if标签中test属性中的不存在&&,使用and代替

             3、foreach

             用于产生一个集合

    工具类Uservo.java

    package com.ghq.model.entity;
    
    import java.util.List;
    
    public class UserVo {
        private List<Integer> idlist;
    
        public List<Integer> getIdlist() {
            return idlist;
        }
    
        public void setIdlist(List<Integer> idlist) {
            this.idlist = idlist;
        }    
    }

    UserDao.java

    //根据模糊姓名和性别查询
    List<User> getUserBynameAndGender(Map<String,Object> m);
    //查询一个主键范围的用户列表
    public List<User> getUsersWithIdList(UserVo vo);

    UserDao.xml

    <select id="getUserBynameAndGender" parameterType="java.util.Map" resultType="user">
        select * from user_tab 
        <!-- where 标签默认会去除第一个and,若输入参数是null,则删除where条件 -->
        <where>
            <if test="username != null and username != ''">
                and username like '%${username}%'
            </if>
            <if test="gender !=null and gender !=''">
                and gender = #{gender}
            </if>
        </where>
      </select>
    
    <select id="getUsersWithIdList" parameterType="UserVo" resultType="user">
          select * from user_tab
          <where>
              <if test="idlist !=null">
                  and id in 
                  <foreach collection="idlist" item="id" open="(" close=")" separator=",">
                      #{id}
                  </foreach>
              </if>
          </where>
      </select>

    单元测试

    public class testmybatis {
        @Test
        public void testgetUserbynameAndGender(){
            SqlSession session = MybatisDb.getSession();
            UserDao userdao = session.getMapper(UserDao.class);
            Map<String,Object> user = new HashMap<String,Object>();
            user.put("username", "张");
            user.put("gender", "女");
            List<User> ulist = userdao.getUserBynameAndGender(user);
            for (User uu : ulist) {
                System.out.println(uu);
            }
            
        }
    
        //批量查询id为1,2,3的用户
        @Test
        public void testgetUsersWithIdList(){
            SqlSession session = MybatisDb.getSession();
            UserDao userdao = session.getMapper(UserDao.class);
            
            UserVo vo = new UserVo();
            List<Integer> idlist = new ArrayList<Integer>();
            idlist.add(1);
            idlist.add(2);
            idlist.add(3);
            vo.setIdlist(idlist);
            List<User> list = userdao.getUsersWithIdList(vo);
            for (User user : list) {
                System.out.println(user);
            }    
        }
    }

    select元素中resultMap属性

      用于解决查询数据表时,查询出的列名和实体的属性名不一致,该属性值要和

      resultMap元素的id一致,该resultMap元素就来完成查询出的列名和实体的属性名的映射,如果查询出的列名和实体的属性名一致,select元素使用resultType就可以,不需要使用resultMap属性。

     

      

  • 相关阅读:
    System.IO.StreamWriter
    C# XML
    C# 泛型
    ACM将一个十进制的数转换为一个十六进制的数输出
    ACM打扫花园问题
    ACM用N个正方体来建造金字塔问可以建造多少层
    输入一串数字找出其中缺少的最小的两个数
    高效算法——B 抄书 copying books,uva714
    暴力求解——POJ 3134Power Calculus
    暴力求解——打表,暴力
  • 原文地址:https://www.cnblogs.com/ghq120/p/8322302.html
Copyright © 2020-2023  润新知