Mybatis学习笔记


一、mybatis查询基本操作

1.MyBatis解决的问题:

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

2.MyBatis可以完成的工作:

  • 注册数据库的驱动,例如 Class.forName(“com.mysql.jdbc.Driver”))
  • 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
  • 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象

查询操作:

1.1 创建数据库与表

  • student表
CREATE TABLE `student` (
  `id` int NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

在这里插入图片描述

1.2 创建maven工程

  • 导入坐标
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.25</version>
    </dependency>
  • 加入maven插件
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>

1.3 创建实体类

  • Student实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;
}
  • 创建Dao接口StudentDao
public interface StudentDao {
    
    //查询student表中所有的数据
    public List<Student> ListAll();

}

1.4 编写 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">

<!--  sql映射文件(sql mapper): 写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接口的全限定名称。-->

<mapper namespace="com.jjh.dao.StudentDao">

    <!--
  4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
   <select>:表示执行查询,select语句
   <update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
   <insert>:表示插入, 放的是insert语句
   <delete>:表示删除, 执行的delete语句
-->

    <!--
       select:表示查询操作。
       id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
           可以自定义,但是要求你使用接口中的方法名称。

       resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
          值写的类型的全限定名称
    -->
    <select id="ListAll" resultType="com.jjh.domain.dto.Student">
        select * from student order by id;
    </select>

</mapper>

1.5 创建 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="test01">
        <!-- environment : 一个数据库信息的配置, 环境
             id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="test01">
            <!--
               transactionManager :mybatis的事务类型
                   type: JDBC(表示使用jdbc中的Connection对象的commitrollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,连接数据库的
                  type:表示数据源的类型, POOLED表示使用连接池
-->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis01"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>


        <!--表示线上的数据库,是项目真实使用的库-->
        <environment id="online">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/online"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置。
           从类路径开始的路径信息。  target/classes(类路径)
        -->
        <mapper resource="com/jjh/dao/StudentDao.xml"/>
        <!--<mapper resource="com/jjh/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>

1.6 创建测试类MyBatisTest

public class App {
    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.jjh.dao.StudentDao" + "." + "ListAll";
        String sqlId = "com.jjh.dao.StudentDao.ListAll";
        //7.执行sql语句,通过sqlId找到语句
        List<Student> StudentList = sqlSession.selectList(sqlId);
        //8.输出结果
        StudentList.forEach(student -> System.out.println(student));
        //9.关闭SqlSession对象      
        sqlSession.close();
    }
}

二、MyBatis查询基本操作

在查询操作上加以改进

2.1 接口中添加查询方法

  • Student添加查询方法
public interface StudentDao {

    //查询student表中所有的数据
    public List<Student> ListAll();

    //插入一条记录
    public Integer InsertOne();

}

2.2 修改映射文件

    <insert id="insertOne">
        insert into student values (#{id},#{name},#{email},#{age});
    </insert>

2.3 测试类

public class App2 {
    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.jjh.dao.StudentDao" + "." + "ListAll";
        String sqlId = "com.jjh.dao.StudentDao.insertOne";
        //7.执行sql语句,通过sqlId找到语句
        Student stu = new Student();
        stu.setId(1005);
        stu.setName("Lucy");
        stu.setEmail("Lucy@gmai.com");
        stu.setAge(20);
        int result = sqlSession.insert(sqlId,stu);

        //mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
//        sqlSession.commit();

        //8.输出结果
        System.out.println(result);
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

2.4 封装MyBatis工具类

public class MyBatisUtils {

    private static SqlSessionFactory sqlSessionFactory = null;

    static {
        String config = "mybatis.xml";
        try {
            InputStream in = Resources.getResourceAsStream(config);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取SqlSession的方法
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = null;
        if (sqlSessionFactory != null){
             sqlSession = sqlSessionFactory.openSession();//需要手动提交事务
        }
        return sqlSession;
    }
    
}

三、MyBatis对象分析

3.1 Resources 类

Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象

3.2 SqlSessionFactoryBuilder 类

  • SqlSessionFactory 的创建 ,需要使SqlSessionFactoryBuilder 对 象 的 build() 方 法
  • 由 于SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁
  • 所以,一般会将该SqlSessionFactoryBuilder对象创建为一个方法内的局部对象,方法结束,对象销毁

3.3 SqlSessionFactory 接口

  • SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可
  • 创建 SqlSession 需要使用 SqlSessionFactory 接口的openSession()方法:
    • openSession(true):创建一个有自动提交功能的 SqlSession
    • openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
    • openSession():同 openSession(false)

3.4 SqlSession 接口

  • SqlSession 接口对象用于执行持久化操作
  • 一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束
  • SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭
  • 再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭

四、MyBatis使用传统Dao的开发方式

4.1 操作步骤

  • 创建Dao接口
public interface StudentDao {
    List<Student> selectStudent();
}
  • 创建接口的映射文件
<mapper namespace="com.jjh.dao.StudentDao">
    <select id="selectStudent" resultType="com.jjh.domain.dto.Student">
        select * from student order by id;
    </select>
</mapper>
  • 在实现类中实现接口中的方法
public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudent() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId = "com.jjh.dao.StudentDao.selectStudent";
        List<Student> studentList = sqlSession.selectList(sqlId);
        sqlSession.close();
        return studentList;
    }
}
  • 在测试类中调用
	@Test
    public void MyBatis01(){
        StudentDao stuDao = new StudentDaoImpl();
        List<Student> studentList = stuDao.selectStudent();
        studentList.forEach(student -> {
            System.out.println(student);
        });
    }

五、MyBatis 框架 Dao 代理

5.1 操作步骤

  • 去掉Dao实现类对象
  • getMapper 获取代理对象
@Test
    public void MyBatis01(){
        /**
         * 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
         * getMapper能获取StudentDao接口对于的实现类对象。
         */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用mapper方法,执行数据库操作
        List<Student> studentList = mapper.selectStudent();
        studentList.forEach(stu->{
            System.out.println(stu);
        });
    }
    @Test
    public void MyBatis02(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
        student.setId(1007);
        student.setName("张大爷");
        student.setEmail("uncleZhang@qq.com");
        student.setAge(220);
        int result = mapper.insertOne(student);
        if (result > 0 ){
            //手动提交事务!
            sqlSession.commit();
            System.out.println("插入成功!!!");
        }
    }

5.2 原理分析

  • StudentDao.xml

parameterType :写在mapper文件中的 一个属性。表示dao接口中方法的参数的数据类型 , 写不写都行

    <select id="selectStudentById" parameterType="int" resultType="com.jjh.domain.Student">
        select id,name, email,age from student where id=${studentId}
    </select>
  • 测试类
@Test
    public void testSelectStudentById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao  =  sqlSession.getMapper(StudentDao.class);
        Student student = dao.selectStudentById(1001);
        System.out.println("student="+student);
    }

1.底层使用动态代理 , 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
2.从java代码中把数据传入到mapper文件的sql语句中

  • 底层jdbc实现的方式
		使用#{}之后, mybatis执行sql是使用的jdbc中的PreparedStatement对象
        由mybatis执行下面的代码:
         1. mybatis创建Connection , PreparedStatement对象
            String sql="select id,name, email,age from student where id=?";
            PreparedStatement pst = conn.preparedStatement(sql);
            pst.setInt(1,1001);

         2. 执行sql封装为resultType="com.bjpowernode.domain.Student"这个对象
            ResultSet rs = ps.executeQuery();
            Student student = null;
            while(rs.next()){
               //从数据库取表的一行数据, 存到一个java对象属性中
               student = new Student();
               student.setId(rs.getInt("id));
               student.setName(rs.getString("name"));
               student.setEmail(rs.getString("email"));
               student.setAge(rs.getInt("age"));
            }

           return student;  //给了dao方法调用的返回值

六、MyBatis多个参数的传递

6.1 使用@Param(重点)

  • 当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}
  • 例如:
    • List<Student> selectStudent( @Param(“personName”) String name ) { … }
    • mapper 文件 select * from student where name = #{ personName}
  • StudentDao类
//多个参数的查询操作
    List<Student> selectMultipleParam(@Param("myName") String name, @Param("myAge") Integer age);
  • 映射文件
    <select id="selectMultipleParam" resultType="com.jjh.domain.dto.Student">
        select * from student where name=#{myName} or age=#{myAge};
    </select>
  • 测试类
    public void Mybatis03(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Student> studentList = mapper.selectMultipleParam("张大爷", 20);
        studentList.forEach(stu->{
            System.out.println(stu);
        });
        sqlSession.close();
    }

6.2 使用对象(重点)

  • 使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数

    • 语法格式:#{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 }
  • javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ property }

  • 创建传递参数的对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QueryParam {

    private String name;
    private Integer age;

}
  • Dao接口
    //对象多为参数传值
    List<Student> selectMultipleObject(QueryParam queryParam);
  • 映射文件
   <!-- <select id="selectMultiObject" resultType="com.jjh.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="selectMultipleObject" resultType="com.jjh.domain.dto.Student">
        select * from student where name=#{name} or age=#{age}
    </select>
  • 测试类
    @Test
    public void Mybatis04(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        QueryParam queryParam = new QueryParam();
        queryParam.setName("张大爷");
        queryParam.setAge(20);
        List<Student> studentList = mapper.selectMultipleObject(queryParam);
        studentList.forEach(stu->{
            System.out.println(stu);
        });
        sqlSession.close();
    }

6.3 使用位置传参

  • Dao文件
/**
     * 多个参数-简单类型的,按位置传值,
     * mybatis.3.4之前,使用 #{0} ,#{1}
     * mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
     */
    List<Student> selectMultiPosition( String name,Integer age);
  • 映射文件
    <!--多个参数使用位置-->
    <select id="selectMultiPosition" resultType="com.jjh.domain.Student">
          select id,name, email,age from student where
          name = #{arg0} or age=#{arg1}
    </select>
  • 测试类
 @Test
    public void testSelectMultiPosition(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        
        List<Student> students = dao.selectMultiPosition("李四",20);

        for(Student stu: students){
            System.out.println("学生="+stu);
        }
        sqlSession.close();
    }

6.5 使用map传值

  • Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数
  • Map 集合使用 String的 key,Object 类型的值存储参数 mapper 文件使用 # { key } 引用参数值

6.6 #和$

1.#:占位符

  • 告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句
  • #{…}代替sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法
  • mapper文件
<select id="selectById" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where id=#{studentId}
</select>
  • 转换为MyBatis的执行
String sql=select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);

2.$ 字符串替换

  • 告诉 mybatis 使用$包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和${}的内容连接起来
  • 主要用在替换表名,列名,不同列排序等操作

七、封装MyBatis的输出结果

7.1 resultType

  • resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名
  • 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身
  • resultType 和 resultMap,不能同时使用。

7.1.1 简单类型

  • 接口方法
int countStudent();
  • mapper文件

resultType可以使用mybatis内置的别名

mapper 文件:
<select id="countStudent" resultType="int">
 select count(*) from student
</select>
  • 测试方法
@Test
public void testRetunInt(){
 int count = studentDao.countStudent();
 System.out.println("学生总人数:"+ count);
}

7.1.2 对象类型

1.执行过程分析:

  • mybatis执行了sql语句,得到java对象
  • resultType结果类型, 指sql语句执行完毕后,数据转为的java对象, java类型是任意的
  • resultType结果类型和值:
    • 类型的全限定名称
    • 类型的别名,例如:java.lang.Integer别名是int
      <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.定义自定义类型的别名:

  • 在mybatis主配置文件中定义,使<typeAlias>定义别名
  • 可以在resultType中使用自定义别名
  • 接口方法
ViewStudent selectByViewStudent(ViewStudent vs);
  • 全局配置别名
<!--
            第一种方式:
            可以指定一个类型一个自定义别名
            type:自定义类型的全限定名称
            alias:别名(短小,容易记忆的)
        -->
    <!--<typeAlias type="com.jjh.domain.Student" alias="stu" />
    <typeAlias type="com.jjh.vo.ViewStudent" alias="vstu" />-->

    <!--
      第二种方式
      <package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
    -->
    <typeAliases>
        <package name="com.jjh.domain"/>
        <package name="com.jjh.domain.dto"/>
    </typeAliases>
  • mapper文件
<select id="selectByViewStudent" resultType="com.jjh.domain.dto.ViewStudent">
        select id,name from student where id=#{id};
    </select>
  • 测试类
@Test
    public void MyBatis05(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        ViewStudent vs = new ViewStudent();
        vs.setId(1005);
        ViewStudent viewStudent = mapper.selectByViewStudent(vs);
        System.out.println(viewStudent);
    }

7.2 resultMap

7.2.1 传统方式使用map作为返回类型

  • dao接口方法
List<Map<Object,Object>> selectByIdReturnMap(Integer id);
  • mapper文件
    <select id="selectByIdReturnMap" resultType="java.util.HashMap">
        select * from student where id>#{id};
    </select>
  • 测试类
@Test
    public void MyBatis05(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Map<Object, Object>> maps = mapper.selectByIdReturnMap(1001);
        maps.stream().forEach(map->{
            System.out.println(map);
        });
        sqlSession.close();
    }

7.2.1 resultMap概述

  • resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性
  • 常用在列名和 java 对象属性名不一样的情况

7.2.3 resultMap操作步骤

1.先定义 resultMap,指定列名和属性的对应关系
2.==在<select>中把 resultType 替换为 resultMap

  • MyStudent实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyStudent {
    private Integer stuId;
    private String stuName;
    private String stuEmail;
    private Integer stuAge;
}
  • Dao接口
List<MyStudent> selectMyStudent ();
  • mapper文件
    <!--
    	定义resultMap
        id:自定义名称,表示你定义的这个resultMap
        type:java类型的全限定名称
    -->
    <resultMap id="myStudentMap" type="com.jjh.domain.dto.MyStudent">
        <!--列名和java属性的关系-->
        <!--注解列,使用id标签
            column :列名
            property:java类型的属性名
        -->
        <id column="id" property="stuId"/>
        <!--非主键列,使用result-->
        <result column="name" property="stuName"/>
        <result column="age" property="stuAge"/>
        <result column="email" property="stuEmail"/>
    </resultMap>
    <!--查询语句-->
    <select id="selectMyStudent" resultMap="myStudentMap">
        select * from student;
    </select>
  • 测试类
    @Test
    public void MyBatisMap(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<MyStudent> myStudents = mapper.selectMyStudent();
        myStudents.forEach(stu->{
            System.out.println(stu);
        });
        sqlSession.close();
    }

7.2.4 实体类属性名和列名不同的处理方式

1.使用列别名和<resultType>

在mapper文件编辑sql语句时给属性名起别名

List<PrimaryStudent> selectUseFieldAlias(QueryParam param);
<select id="selectUseFieldAlias" 
resultType="com.bjpowernode.domain.PrimaryStudent">
 select id as stuId, name as stuName,age as stuAge
 from student where name=#{queryName} or age=#{queryAge}
</select>

2.使用<resultMap>

List<PrimaryStudent> selectUseDiffResultMap(QueryParam param);
<!-- 创建 resultMap
 id:自定义的唯一名称,在<select>使用
 type:期望转为的 java 对象的全限定名称或别名 
--> <resultMap id="primaryStudentMap" 
type="com.jjh.domain.PrimaryStudent">
 <!-- 主键字段使用 id -->
 <id column="id" property="stuId" />
 <!--非主键字段使用 result-->
 <result column="name" property="stuName"/>
 <result column="age" property="stuAge" />
</resultMap>
<!--resultMap: resultMap 标签中的 id 属性值--> <select id="selectUseDiffResultMap" resultMap="primaryStudentMap">
 select id,name,email,age from student
 where name=#{queryName} or age=#{queryAge}
</select>

7.3 模糊查询like

需求:查询带有“大”的数据

  • Dao接口
    //模糊查询
    Student selectLikeOne(String name);
  • mapper文件
    <!--模糊查询-->
    <select id="selectLikeOne" resultType="com.jjh.domain.dto.Student">
        select * from student where name like "%" #{stuName} "%"
    </select>
  • 测试类
@Test
    public void MyBatisLike(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        String name = "大";
        Student student = mapper.selectLikeOne(name);
        System.out.println(student);
        sqlSession.close();
    }

八、动态SQL

8.1 动态sql之<if>

  • 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中
  • 语法:<if test=”条件”> sql 语句的部分 </if>
  • Dao接口
public interface StudentDao {
    List<Student> selectIf(Student condition);
}
  • mapper文件
    <select id="selectIf" resultType="com.jjh.domain.dto.Student">
        select * from student
        where 1=1
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>
  • 测试类
@org.junit.Test
    public void demo01(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //使用对象传递参数
        Student stu = new Student();
        stu.setAge(19);
        stu.setName("张大爷");
        List<Student> studentList = mapper.selectIf(stu);
        studentList.forEach(student -> {
            System.out.println(student);
        });
        sqlSession.close();
    }

<if>不足之处:

  • <if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句
  • 若 where 后的所有<if/>条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL会出错
  • 所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率

8.2 动态 SQL 之<where>

  • 使用<where/>标签,在有查询条件时,可以自动添加上 where 子句
  • 没有查询条件时,不会添加where 子句
  • 需要注意的是,第一个<if/>标签中的 SQL 片断,可以不包含 and
  • 但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
  • Dao接口
List<Student> selectWhereIf(Student condition);
  • mapper文件
    <select id="selectWhereIf" resultType="com.jjh.domain.dto.Student">
        select * from student
        <where>
            <if test="name != null and name != ''">
                name=#{name}
            </if>
            <if test="age > 0">
                and age>#{age}
            </if>
        </where>
    </select>
  • 测试类
    @org.junit.Test
    public void demo02(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        Student stu = new Student();
//        stu.setName("王麻子");
        stu.setAge(19);
        List<Student> studentList = mapper.selectWhereIf(stu);
        studentList.forEach(student->{
            System.out.println(student);
        });
        sqlSession.close();
    }

8.3 动态 SQL 之<foreach>

1.<foreach/>标签用于实现对于数组与集合的遍历

  • collection 表示要遍历的集合类型, list ,array 等
  • open、close、separator 为对遍历内容的 SQL 拼接

2.<foreach/>标签的属性及其作用:

  • collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
  • item:自定义的,表示数组和集合成员的变量
  • open:循环开始是的字符
  • separator:集合成员之间的分隔符

8.2.1 遍历 List<简单类型>

  • Dao接口
List<Student> selectStudentForEach(List<Integer> idList);
  • mapper文件
    <select id="selectStudentForEach" resultType="com.jjh.domain.dto.Student">
        select * from student 
        where id in 
        <foreach collection="list" item="myId" open="(" close=")" separator=",">
            #{myId}
        </foreach>
    </select>
  • 测试类
    @org.junit.Test
    public void demo03(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);
        List<Student> studentList = mapper.selectStudentForEach(list);
        studentList.forEach(stu->{
            System.out.println(stu);
        });
        sqlSession.close();
    }

8.2.2 遍历 List<对象类型>

  • Dao接口
List<Student> selectStudentForEach2(List<Student> stuList);
  • mapper文件
    <select id="selectStudentForEach2" resultType="com.jjh.domain.dto.Student">
        select * from student
        where id in 
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>
    </select>
  • 测试类
    @org.junit.Test
    public void demo04(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Student> stuList = new ArrayList<>();
        Student s1 = new Student();
        s1.setId(1005);
        stuList.add(s1);

        s1 = new Student();
        s1.setId(1002);
        stuList.add(s1);
        List<Student> studentList = mapper.selectStudentForEach2(stuList);
        studentList.forEach(stu->{
            System.out.println(stu);
        });
        sqlSession.close();
    }

8.4 动态 SQL 之代码片段

  • <sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用<include/>子标签
  • <sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL的任何位置。
  • Dao接口
List<Student> selectStudentSqlFragment(List<Student> stuList);
  • mapper文件
<!--创建 sql 片段 id:片段的自定义名称--> 
<sql id="studentSql">
 	select id,name,email,age from student
</sql> 
<select id="selectStudentSqlFragment" 
	resultType="com.jjh.domain.Student">
 	<!-- 引用 sql 片段 -->
 	<include refid="studentSql"/>
	<if test="list !=null and list.size > 0 ">
		where id in
	<foreach collection="list" open="(" close=")" 
		item="stuobject" separator=",">
		#{stuobject.id}
	</foreach>
 </if>
</select>

九、MyBatis配置文件

  • 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>

    <!--指定properties文件的位置,从类路径根开始找文件-->
    <properties resource="jdbc.properties" />

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <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>

    <!--配置插件-->
    <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>

9.1 使用数据库属性配置文件

为了方便对数据库连接的管理,DB 连接四要素数据一般都是存放在一个专门的属性文件中的。MyBatis主配置文件需要从这个属性文件中读取这些数据

1.在 classpath 路径下创建properties文件
2.使用 properties 标签
3.使用 key 指定值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值