02 MyBatis框架

1. 软件开发常用结构

1.1 三层架构

  1. 界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。
  2. 业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
  3. 数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库.

三层的处理请求的交互:
用户—> 界面层—>业务逻辑层—>数据访问层—>DB 数据库
在这里插入图片描述
为什么要使用三层?
1,结构清晰、耦合度低, 各层分工明确
2,可维护性高,可扩展性高
3,有利于标准化
4,开发人员可以只关注整个结构中的其中某一层的功能实现
5,有利于各层逻辑的复用

三层对应的处理框架

  • 界面层—servlet—springmvc(框架)
  • 业务逻辑层—service类–spring(框架)
  • 数据访问层—dao类–mybatis(框架)

2. MyBatis框架介绍

2.1 MyBatis 解决的主要问题

  • 传统JDBC编程存在的问题
  • 代码比较多,开发效率低
  • 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
  • 对 ResultSet 查询的结果,需要自己封装为 List
  • 重复的代码比较多些
  • 业务代码和数据库的操作混在一起
    public void findStudent() {
          
          
    	 Connection conn = null;
    	 Statement stmt = null;
    	 ResultSet rs = null;
    	 try {
          
          
    		 //注册 mysql 驱动
    		 Class.forName("com.mysql.jdbc.Driver");
    		 //连接数据的基本信息 url ,username,password
    		 String url = "jdbc:mysql://localhost:3306/springdb";
    		 String username = "root";
    		 String password = "123456";
    		 //创建连接对象
    		 conn = DriverManager.getConnection(url, username, password);
    		 //保存查询结果
    		 List<Student> stuList = new ArrayList<>();
    		 //创建 Statement, 用来执行 sql 语句
    		 stmt = conn.createStatement();
    		 //执行查询,创建记录集,
    		 rs = stmt.executeQuery("select * from student");
    		 while (rs.next()) {
          
          
    			 Student stu = new Student();
    			 stu.setId(rs.getInt("id"));
    			 stu.setName(rs.getString("name"));
    			 stu.setAge(rs.getInt("age"));
    			 //从数据库取出数据转为 Student 对象,封装到 List 集合
    			 stuList.add(stu);
    	 }
    	
    	 } catch (Exception e) {
          
          
    	 	e.printStackTrace();
    	 } finally {
          
          
    		 try {
          
          
    		 //关闭资源
    			 if (rs != null) ;
    			 {
          
          
    			 	rs.close();
    			 }
    			 if (stmt != null) {
          
          
    			 	stmt.close();
    			 }
    			 if (conn != null) {
          
          
    			 	conn.close();
    			 }
    	 } catch (Exception e) {
          
          
    	 	e.printStackTrace();
    	 	}
    	} 
    }
    
  • MyBatis 解决的主要问题

减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。

MyBatis 可以完成:
1. 注册数据库的驱动,例如 Class.forName(“com.mysql.jdbc.Driver”))
2. 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
3. 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象
	List<Student> list = new ArrayLsit<>();
	ResultSet rs = state.executeQuery(“select * from student”);
	while(rs.next){
	 Student student = new Student();
	 student.setName(rs.getString(“name”));
	 student.setAge(rs.getInt(“age”));
	 list.add(student);
	}
4.关闭资源
	ResultSet.close() , Statement.close() , Conenection.close()

2.2 IDEA中如何使用MyBatis

MyBatis入门案例

  1. 第一步: 创建 mysql 数据库和表

    数据库名 ssm ;表名 student 在这里插入图片描述

  2. 第二步:创建 maven 工程
    在这里插入图片描述

  3. 第三步:在Pom文件加入 MyBatis依赖和数据库驱动依赖

       <!--mybatis依赖 -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.1</version>
        </dependency>
        <!--mysql驱动 -->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.23</version>
        </dependency>
      </dependencies>
    
  4. 第四步:编写 Student 实体类

    创建包 com.bjpowernode.entity, 包中创建 Student 类

    package com.bjpowernode.entity;
    //实体类推荐和表名一样
    public class Student {
          
          
        //定义属性,目前要求是属性名和列名一样
        private Integer id;
        private String name;
        private String email;
        private Integer age;
        public Student(){
          
          }
        public Student(Integer id, String name, String email, Integer age) {
          
          
            this.id = id;
            this.name = name;
            this.email = email;
            this.age = age;
        }
    
        public Integer getId() {
          
          
            return id;
        }
    
        public void setId(Integer id) {
          
          
            this.id = id;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        public void setName(String name) {
          
          
            this.name = name;
        }
    
        public String getEmail() {
          
          
            return email;
        }
    
        public void setEmail(String email) {
          
          
            this.email = email;
        }
    
        public Integer getAge() {
          
          
            return age;
        }
    
        public void setAge(Integer age) {
          
          
            this.age = age;
        }
    
        @Override
        public String toString() {
          
          
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", email='" + email + '\'' +
                    ", age=" + age +
                    '}';
        }
    }	
    
  5. 第五步:编写 Dao 接口 StudentDao
    创建 com.bjpowernode.dao 包,创建 StudentDao 接口

    package com.bjpowernode.dao;	
    import com.bjpowernode.entity.Student;	
    import java.util.List;	
    //接口操作student表
    public interface StudentDao {
          
          
        //查询student表的所有数据
        public List<Student> selectStudents();
    
        //插入方法
    
        /**
         *
         * @param student:插入数据库中的数据
         * @return int:表示执行insert操作后,影响数据库中的行数
         */
        public int insertStudents(Student student);
    }	
    
  6. 第六步:编写 Dao 接口 Mapper 映射文件 StudentDao.xml
    要求:

    1. 在 dao 包中创建文件 StudentDao.xml
    2. 要求 StudentDao.xml 文件名称和接口 StudentDao 一样,区分大小写的一样。
    <?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.bjpowernode.dao.StudentDao">
        <!--
            select:表示查询操作
            id:你要执行sql语句的唯一标识,mybatis会使用这个id的值找到要执行的sql语句
                可以自定义,但是要求你要求你使用接口中的方法名称。
            resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
                值写的是类型的全限定名称。
        -->
        <select id="selectStudents" resultType="com.bjpowernode.entity.Student">
            select id,name,email,age from student
        </select>
        <!--插入操作-->
        <insert id="insertStudents">
            insert into student values(#{id},#{name},#{email},#{age})
        </insert>
    </mapper>
    
    <!--
        sql映射文件:写sql语句,mybatis会执行这些sql
    
        1. 指定约束文件
            <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
            mybatis-3-mapper.dtd:是约束文件,扩展名是dtd的
        2. 约束文件的作用:限制和检查在当前文件中出现的标签,属性必须符合mybatis的要求
    
        3. mapper是当前文件的根标签,必须的
           namespace 是命名空间,唯一值的,可以是自定义的字符串,要求你使用dao接口的全限定名称.
    
        4. 在当前文件中可以使用特点的标签,表示数据库的特定操作
            <select>:表示执行查询
            <update>:表示更新数据库的操作,就是在<update>标签中写的是update sql语句
            <insert>:表示插入
            <delete>:表示的是删除
    -->
    
  7. 第七步:创建 MyBatis 主配置文件
    项目 src/main 下创建 resources 目录,设置 resources 目录为 resources root
    创建主配置文件:名称为 mybatis.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">
    <configuration>
        <!--settings:控制mybatis全局行为的-->
        <settings>
            <!--设置mybatis输出日志-->
            <setting name="logImpl" value="STDOUT_LOGGING" />
        </settings>
        <!--环境配置:数据库的连接信息
            default : 必须和某个environment中的id值一样
            告诉mybatis即将连接的是哪个数据库的的连接信息,也就是访问哪个数据库
            (这里的不同不是数据库产品的不同,而是在不同项目运行状态下使用的数据库不用)
                如:在线上和本地使用的数据库不同,
        -->
        <environments default="mydev">
            <!--environment:一个数据库信息的配置,环境
                id:一个唯一值,自定义的,表示环境的名称
            -->
            <environment id="mydev">
                <!--transactionManager:mybatis的事务类型
                    type:JDBC(表示使用jdbc中的connection对象的commit,rollback做事务处理)-->
                <transactionManager type="JDBC"/>
                <!--dataSource:表示数据源,连接数据库的
                    type:表示数据源的类型,POOLED表示使用的连接池
                -->
                <dataSource type="POOLED">
                    <!--
                        driver,url,username,password 是固定的们不能自定义
                    -->
                    <!--driver,数据库驱动类名-->
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <!--url,数据库连接地址-->
                    <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                    <!--username,连接数据库的用户名称-->
                    <property name="username" value="root"/>
                    <!--password,连接数据库的用户的密码-->
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--sql映射文件的地址-->
        <mappers>
            <!--一个mapper标签指定一个文件的位置
                从类路径开始的路径信息
            -->
            <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        </mappers>
    </configuration>
    <!--
        mybatis的主配置文件:主要定义了数据库的配置信息,sql映射文件的位置
    
    
        1. 约束文件
            <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        2. 根标签:<configuration>
    -->
    
  8. 创建测试类

package com.bjpowernode;

import com.bjpowernode.entity.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyApp {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //访问mybatis读取student表中内容
        // 1.定义mybatis主配置文件的名称,从类路径的根路径开始(target/classes)
        String config = "mybatis.xml";
        // 2.读取config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        // 3.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        // 5.【重要的】获取 SqlSession对象,从SqlSessionFactory中会获取SqlSession
        SqlSession sqlSession = factory.openSession();
        // 6. 指定要执行的sql语句的标识。sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
        // 7.执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);

        // 8.输出结果
        for (Student stu:studentList) {
    
    
            System.out.println(stu);
        }
        // 9.关闭SqlSession对象
        sqlSession.close();
    }
}

2.3 主要类的介绍

  • Resources: mybatis中的一个类, 负责读取主配置文件
    InputStream in = Resources.getResourceAsStream(“mybatis.xml”);

  • SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    //创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(in);

  • SqlSessionFactory : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。

     在整个项目中,有一个就够用了。
       SqlSessionFactory:接口  , 接口实现类: DefaultSqlSessionFactory
       SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();
    
       openSession()方法说明:
     1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
     2. openSession(boolean): openSession(true)  获取自动提交事务的SqlSession. 
        openSession(false)  非自动提交事务的SqlSession对象
    
  • SqlSession:

      SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
      SqlSession接口的实现类DefaultSqlSession。
    
     使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
     在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
    

3. MyBatis框架Dao代理

小便捷:创建MyBatis的util工具类封装一下部分类的使用

package com.bjpowernode.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {
    
    
    private static SqlSessionFactory factory = null;
    static {
    
    
        //读取mybatis主配置文件
        String config = "mybatis.xml";//需要和你的项目中名字一样
        try {
    
    
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
             factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
    //获取sqlSession方法
    public static SqlSession getSqlSession(){
    
    
        SqlSession sqlSession = null;
        if (factory != null) {
    
    
            sqlSession =  factory.openSession();//非自动提交事务
        }
        return sqlSession;
    }
}

3.1 Dao 代理实现 CURD

(1) 去掉 Dao 接口实现类
在这里插入图片描述

(2) getMapper 获取代理对象
只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。

package com.bjpowernode;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.entity.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class TestMyBatis {
    
    
    @Test
    public void testSelectStudents(){
    
    
        /**
         * 使用MyBatis的动态代理机制,使用sqlSession,getMapper(dao接口)
         * getMapper能够获取的是dao接口的实现类对象
         */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //调用dao的方法执行数据库的操作
        List<Student> studentList = dao.selectStudents();
        for (Student stu:studentList) {
    
    
            System.out.println(stu);
        }
    }
    @Test
    public void testInsertStudents(){
    
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //调用dao的方法执行数据库的操作
        int nums = dao.insertStudents(new Student(1005, "刘备", "[email protected]", 25));
        sqlSession.commit();
        System.out.println("添加成员" + nums);
    }
}

3.2 深入理解参数

3.2.1 parameterType

parameterType: 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到mapper 文件的 sql 语句。

例如:

<delete id="deleteStudent" parameterType="int">
	 delete from student where id=#{studentId}
</delete>

等同于

<delete id="deleteStudent" parameterType="java.lang.Integer">
	 delete from student where id=#{studentId}
</delete>

如:

<?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.bjpowernode.dao.StudentDao">
    <!--
        parameterType : dao接口中方法参数的数据类型
        parameterType的值是java数据类型全限定名称或者是mybatis定义的别名
        例如:parameterType="java.lang.Integer"
           或    parameterType="int"
        注意:parameterType不是强制的,mybatis可以通过反射机制发现接口中的参数的数据类型
            所以可以没有,一般不写。
     -->
    <select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bjpowernode.entity.Student">
        select id,name,email,age from student where id = #{id}
    </select>
</mapper>

3.2.2 MyBatis 传递参数

  • 一个简单类型的参数:

     简单类型: mybatis把java的基本数据类型和String都叫简单类型。
     在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
    
     接口:public Student  selectStudentById(Integer id) 
     mapper:select id,name, email,age from student where id=#{studentId}
    
  • 多个参数,使用@Param命名参数

      接口 public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
       使用  @Param("参数名")  String name 
     mapper文件:
          <select>
              select * from student where name=#{myname} or age=#{myage}
     	  </select>
    
  • 多个参数,使用java对象
    语法 #{属性名}

<?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.bjpowernode.dao.StudentDao">
    <select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">
        select id,name, email,age from student where id=${studentId}
    </select>

    <!--多个参数,使用@Param命名-->
    <select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
         select id,name, email,age from student where name=#{myname} or age=#{myage}
    </select>

    <!--多个参数, 使用java对象的属性值,作为参数实际值
        使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。
                    javaType:指java中的属性数据类型。
                    jdbcType:在数据库中的数据类型。
                    例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}

        我们使用的简化方式: #{属性名}  ,javaType, jdbcType的值mybatis反射能获取。不用提供

    -->
   <!-- <select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
           name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
           or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
    </select>-->

    <select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
           name=#{paramName}   or age=#{paramAge}
    </select>

    <select id="selectMultiStudent" resultType="com.bjpowernode.domain.Student">
         select id,name, email,age from student where name=#{name} or age=#{age}
    </select>

    <!--多个参数使用位置-->
    <select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
          name = #{arg0} or age=#{arg1}
    </select>

    <!--多个参数,使用Map , 使用语法 #{map的key}-->
    <select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
          name = #{myname} or age=#{age1}
    </select>

    <!--使用 ${}-->
    <select id="selectUse$" resultType="com.bjpowernode.domain.Student">
         select * from student where name=${myname}
    </select>

    <!--
       $替换列名
    -->
    <select id="selectUse$Order" resultType="com.bjpowernode.domain.Student">
         select * from student order by ${colName}
    </select>
</mapper>

package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;
import com.bjpowernode.vo.QueryParam;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface StudentDao {
    
    

    /**
     * 一个简单类型的参数:
     *   简单类型: mybatis把java的基本数据类型和String都叫简单类型。
     *  在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
     */
    public Student selectStudentById(@Param("studentId") Integer id);

    /**
     * 多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")
     */
    List<Student> selectMultiParam(@Param("myname") String name,
                                   @Param("myage") Integer age);


    /**
     * 多个参数,使用java对象作为接口中方法的参数
     */
    List<Student> selectMultiObject(QueryParam param);

    List<Student> selectMultiStudent(Student student);

    /**
     * 多个参数-简单类型的,按位置传值,
     * mybatis.3.4之前,使用 #{0} ,#{1}
     * mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
     */
    List<Student> selectMultiPosition( String name,Integer age);

    /**
     * 多个参数,使用Map存放多个值
     */
    List<Student> selectMultiByMap(Map<String,Object> map);



    List<Student> selectUse$(@Param("myname") String name);

    List<Student> selectUse$Order(@Param("colName") String colName);
}

3.2.3 # 和 $

select id,name, email,age from student where id=#{studentId}

# 的结果: select id,name, email,age from student where id=? 

select id,name, email,age from student where id=${studentId}

$ 的结果:select id,name, email,age from student where id=1001
  • .# 和 $区别
  1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
  2. #能够避免sql注入,更安全。
  3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  4. $有sql注入的风险,缺乏安全性。

3.2.4 resultMap和resultType 及模糊查询Like

1)resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
   resultType结果类型的它值 
   	1. 类型的全限定名称   2. 类型的别名, 例如 java.lang.Integer别名是int


    处理方式:
	   1. mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
	   2. mybatis把ResultSet指定列值付给同名的属性。


		<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
     		 select id,name, email,age from student
  	    </select>

	  对等的jdbc
	  ResultSet rs = executeQuery(" select id,name, email,age from student" )
	  while(rs.next()){
           Student  student = new Student();
				student.setId(rs.getInt("id"));
				student.setName(rs.getString("name"))
	  }

2)  定义自定义类型的别名
	    1)在mybatis主配置文件中定义,使<typeAlias>定义别名
		2)可以在resultType中使用自定义别名
3)resultMap:结果映射, 指定列名和java对象的属性对应关系。
	    1)你自定义列值赋值给哪个属性
		 2)当你的列名和属性名不一样时,一定使用resultMap
	 resultMap和resultType不要一起用,二选一
<?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.bjpowernode.dao.StudentDao">

    <!--selectStudentReturnViewStudent-->
    <select id="selectStudentReturnViewStudent" resultType="ViewStudent">
        select id,name  from student where id=#{sid}
    </select>


    <!--sql执行后返回一行一列-->
    <!--<select id="countStudent" resultType="int">-->
    <select id="countStudent" resultType="java.lang.Integer">
        select count(*) from student
    </select>

    <!--返回Map
        1)列名是map的key, 列值是map的value
        2)只能最多返回一行记录。多余一行是错误
    -->
    <select id="selectMapById" resultType="java.util.HashMap">
        select id,name,email from student where id=#{stuid}
    </select>

    <!--使用resultMap
        1)先定义resultMap
        2)在select标签,使用resultMap来引用1定义的。
    -->

    <!--定义resultMap
        id:自定义名称,表示你定义的这个resultMap
        type:java类型的全限定名称
    -->
    <resultMap id="studentMap" type="com.bjpowernode.domain.Student">
        <!--列名和java属性的关系-->
        <!--注解列,使用id标签
            column :列名
            property:java类型的属性名
        -->
        <id column="id" property="id" />
        <!--非主键列,使用result-->
        <result column="name" property="name" />
        <result column="email" property="email" />
        <result column="age" property="age" />

    </resultMap>
    <select id="selectAllStudents" resultMap="studentMap">
        select id,name, email , age from student
    </select>


    <resultMap id="myStudentMap" type="com.bjpowernode.domain.MyStudent">
        <!--列名和java属性的关系-->

        <id column="id" property="stuid" />
        <!--非主键列,使用result-->
        <result column="name" property="stuname" />
        <result column="email" property="stuemail" />
        <result column="age" property="stuage" />

    </resultMap>
    <!--列名和属性名不一样:第一种方式-->
    <select id="selectMyStudent" resultMap="myStudentMap">

         select id,name, email , age from student
    </select>

    <!--列名和属性名不一样:第二种方式
       resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
    -->
    <select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">
        select id as stuid ,name as stuname, email as stuemail , age stuage from student
    </select>


    <!--第一种 like , java代码指定 like的内容-->
    <select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where name like #{name}
    </select>

    <!--第二种方式:在mapper文件中拼接 like的内容-->
    <select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where name  like "%" #{name} "%"
    </select>
</mapper>

4. 动态sql

动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。

动态sql的实现

使用的是mybatis提供的标签, <if> ,<where>,<foreach>

4.1 if 标签使用

 <!--if
         <if test = "使用参数java对象的属性值作为判断条件  语法规则:属性名 = xxx值"
    -->
    <select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/>
        where
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>

缺点:当使用多个if标签命令时,会产生SQL语法错误。如下所示:

<sql id="studentSql">
    select id,name,email,age from student
</sql>
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/>
        where
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
 </select>
 在输入参数时:若判断name时不符合条件,而age符合条件,此时的sql语句会变为:
	 select id,name,email,age from student or age = ?
此时存在语法错误。

解决方法:
法1 : 如下所示
缺陷:在实际情况中,若后面两个条件都不符合时会使用 1 = 1查询到所有数据,但是sql原意是查询不到数据。

	<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
	        <include refid="studentSql"/>
	        where
	        1 = 1
	        <if test="name != null and name != ''">
	          and  name = #{name}
	        </if>
	        <if test="age > 0">
	            or age > #{age}
	        </if>
	 </select>

法2 : 使用where标签,不存在上述缺陷

4.2 where 标签使用

用来包含 多个if的, 当多个if有一个成立的, where会自动增加一个where关键字,并去掉 if中多余的 and ,or等。

 <!--where : <where> <if> </if>... </where>
    -->
    
    <select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/>
        <where>
            <if test="name != null and name != ''">
                name = #{name}
            </if>
            <if test="age > 0">
                or age > #{age}
            </if>
        </where>
    </select>

4.3 foreach 标签使用

foreach 标签用于实现对于数组与集合的遍历。对其使用,需要注意:
➢ collection 表示要遍历的集合类型, list ,array 等。
➢ open、close、separator 为对遍历内容的 SQL 拼接。

语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符" 
item="集合中的成员" separator="集合成员之间的分隔符">
 #{item 的值}
</foreach>
<!--foreach使用1  ,当传入的List集合中存储的是基本数据类型时
    -->
    <select id="selectStudentOne" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/>  where id in
        <foreach collection="list" item="myid" open="(" close=")" separator=",">
            #{myid}
        </foreach>
    </select>

    <!--foreach使用2   当传入的List集合中存储的是引用数据类型时,直接使用引用.属性名 的方式。
 -->
    <select id="selectStudentTwo" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/> where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>

    </select>

4.4 sql代码片段

步骤
	 1.先定义 <sql id="自定义名称唯一">  sql语句, 表名,字段等 </sql>
     2.再使用, <include refid="id的值" />
 <!--定义sql代码片段-->
    <sql id="studentSql">
        select id,name,email,age from student
    </sql>
<!--if
         <if test = "使用参数java对象的属性值作为判断条件  语法规则:属性名 = xxx值"
    -->
    <select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql"/>
        where
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>

5. mybatis主配置文件

主配置文件特点:
1. 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"> 
 2.根元素,<configuration>
 3.主要包含内容:
	➢ 定义别名
	➢ 数据源
	➢ mapper 文件  
<?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>
    <!--指定properties文件的位置,从类路径根开始找文件-->
    <properties resource="jdbc.properties" />

    <!--settings:控制mybatis全局行为-->
<!--    <settings>-->
<!--        &lt;!&ndash;设置mybatis输出日志&ndash;&gt;-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--    </settings>-->

    <!--定义别名-->
    <typeAliases>
        <!--
            第一种方式:
            可以指定一个类型一个自定义别名
            type:自定义类型的全限定名称
            alias:别名(短小,容易记忆的)
        -->
        <!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
        <typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->

        <!--
          第二种方式
          <package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
        -->
        <package name="com.bjpowernode.domain"/>
        <package name="com.bjpowernode.vo"/>
    </typeAliases>
    <!--配置pagehelper插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor" />
    </plugins>

    <environments default="mydev">
        <environment id="mydev">
            <!--
              transactionManager:mybatis提交事务,回滚事务的方式
                 type: 事务的处理的类型
                     1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
                     2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
                          数据源表示Connection对象的。

               type:指定数据源的类型
                  1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
                  2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
                              mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
                  3)JNDI:java命名和目录服务(windows注册表)
            -->
            <dataSource type="POOLED">
                <!--数据库的驱动类名-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="${jdbc.url}"/>
                <!--访问数据库的用户名-->
                <property name="username" value="${jdbc.user}"/>
                <!--密码-->
                <property name="password" value="${jdbc.passwd}"/>
            </dataSource>
        </environment>

    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--第一种方式:指定多个mapper文件-->
        <!--<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <mapper resource="com/bjpowernode/dao/OrderDao.xml" />-->

        <!--第二种方式: 使用包名
            name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
            使用package的要求:
             1. mapper文件名称需要和接口名称一样, 区分大小写的一样
             2. mapper文件和dao接口需要在同一目录
        -->
        <package name="com.bjpowernode.dao"/>
        <!-- <package name="com.bjpowernode.dao2"/>
         <package name="com.bjpowernode.dao3"/>-->
    </mappers>
</configuration>

6. 扩展

6.1 PageHelper 分页方法

使用方法:

  1. 第一步 : 现在POM中加入PageHelper 依赖

    <dependency>
     <groupId>com.github.pagehelper</groupId>
     <artifactId>pagehelper</artifactId>
     <version>5.1.10</version>
    </dependency> 
    
  2. 第二步:在mybatis主配置文件中加入插件

    	<!--在<environments>之前加入-->
    	<plugins>
    	 <plugin interceptor="com.github.pagehelper.PageInterceptor" />
    	</plugins>
    
  3. PageHelper 对象,查询语句之前调用 PageHelper.startPage 静态方法。

    @Test
    public void testSelect() throws IOException {
          
          
    //获取第 1 页,3 条内容
    PageHelper.startPage(1,3);
     List<Student> studentList = studentDao.selectStudents();
     studentList.forEach( stu -> System.out.println(stu));
    }
    

猜你喜欢

转载自blog.csdn.net/qq_28384023/article/details/116430783