myBatis 入门学习

myBatis 入门学习

0. 相关概念

0.1 框架和工具类

  • 工具类

    • 对程序中一小段代码的封装。项目中大多数代码还是需要我们写。

  • 框架

    • 通俗理解框架

    • 可以看做一个半成品的软件/项目。使用框架开发项目,项目中半数以上代码就不需要 我们编写了。

    • 我们一般需要配置(大多数框架都是重配置轻编码的)+少量编码,就可完成项目中的需求。

    • 框架的目的 就是为了简化编码eg:Mybatis 我们在学习完Mybatis之后,dao层会更简单。你只需要写一个dao接口,然后写一个SQL语句,dao层就已经写完了。

  • 学习步骤

    • 这个框架能干什么?

    • 导包+配置

    • 框架少量的API,少量编码

0.2 ORM

  • Object Relational Mapping 对象关系映射的思想

  • 对象 - Java中的对象 关系-关系型数据库中表的记录 映射 - 一对一关联起来

  • java项目中的每一个实体类,对应数据库中的一个 java类中的属性,对应数据库表中的字段 java类中的一个实体对象,对应一个数据表中的一条记录

  • 全自动ORM框架:hibernate

    通过操作实体对象,就可以完成对数据库表中记录的操作。复杂业务性能低下,不可定制,学习成本高。

  • 半自动的ORM框架:Mybatis,ibatis

    基于ORM,但是SQL语句需要我们自己编写。自己优化SQL,可定制性强,效率高。

 

0.3 Mybatis&原生JDBC

  • 原生jdbc

    • 注册驱动,设置连接参数

    • 获取连接

    • 获取执行对象

    • 设置SQL参数并执行SQL语句

    • 封装结果集并封装成实体对象

    • 释放资源

    相同的内容已经抽取到工具类中(上述删除线标识的步骤)

    模板化(步骤不变,部分步骤相同,上述加粗的内容)的操作,也是可以抽取封装的。

    但是相同的步骤中又有不同的地方,不同的地方如果也要实现解耦,需要通过配置来实现

  • Mybatis解决方案

    • 连接复用:使用数据库连接池初始化并管理连接

    • 解耦:将SQL语句和设置到SQL中的参数抽取到xml配置文件中

    • 自动封装:通过反射内省等技术,实现查询结果集字段实体属性自动映射并赋值

  • Mybatis框架抽取后的样子

 

 

 

 

 

 

  • Mybatis简介

    • 是一个数据持久层(DAO)框架,封装共性内容让使用者只关注SQL本身。结合了ORM思想,是一个ORM半自动的框架。

    • 使用Mybatis之后,我们只需要定义一个Dao层接口+存储SQL的配置文件(Mybatis映射配置文件),就可以完成Dao层内容。

 

1. Mybatis快速入门

1.1 Mybatis快速入门步骤

  • 导入Jar包

    • mybatis-3.5.3.jar

    • mysql-connector-java-5.1.37-bin.jar

    • log4j-1.2.17.jar

  • 编写Mybatis核心配置文件:mybatis-config.xml

    • 连接数据库四要素

    • <mapper>标签中映射文件路径不是. 是/ 建议复制,不要手敲

  • 编写映射文件:StudentDao.xml

  • 编写POJO类和Dao层接口,初始化数据库表及数据

  • SQL

  • 实体类

  • 接口

  • 测试

  • 小经验

    • 直接生成mybatis的两类xml文件

       

    • Mybatis映射配置文件和接口之间相互跳转

核心配置文件

 
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2  <!DOCTYPE configuration
 3          PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4          "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5  <configuration>
 6      <environments default="development">
 7          <environment id="development">
 8              <transactionManager type="JDBC"/>
 9              <dataSource type="POOLED">
10                  <!-- 连接数据库四要素 -->
11                  <property name="driver" value="com.mysql.jdbc.Driver"/>
12                  <property name="url" value="jdbc:mysql:///web17_mybatis01"/>
13                  <property name="username" value="root"/>
14                  <property name="password" value="root"/>
15              </dataSource>
16          </environment>
17      </environments>
18  ​
19  ​
20      <!-- 加载映射配置文件 -->
21      <mappers>
22          <mapper resource="com/itheima/dao/StudentDao.xml"/>
23      </mappers>
24  </configuration>

 

 

映射配置文件

 
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2  <!--
 3      xml文档第一行是文档声明,必须在首行
 4      接下来是:命名空间。作用如下:
 5          1. 引入dtd文件
 6          2. 对文档中标签及其属性进行约束
 7   -->
 8  <!DOCTYPE mapper
 9          PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
10          "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
11  ​
12  <!-- 把当前这个xml配置文件当做对应接口的实现类
13          通过namespace属性指向要被实现的接口,接口代理的方式必须这样写
14  ​
15   -->
16  <mapper namespace="com.itheima.dao.StudentDao">
17      <!--
18          标签名:select  表示查询
19              id属性   id唯一标识,要配置被实现的接口中的方法
20              resultType属性    方法的结果(集合中泛型)的类型,全限定类名,不能省略
21              parameterType属性,方法发参数的类型,全限定类名,可以省略
22              标签体中书写SQL语句
23          整个标签被称之为:statement
24  ​
25       -->
26          <select id="findById" resultType="com.itheima.domain.Student">
27              select * from student where  id = 1;
28          </select>
29  </mapper>

 

接口StudentDao.java

 
1 public interface StudentDao {
2      Student findById();
3  }

 

 

测试类MybatisTest.java

View Code

 

 

 

2. API

2.1 Resources

读取配置的文件的工具类

InputStream getResourceAsStream("配置文件相对于类路径的相对路径");

2.2 SqlSessionFactoryBuilder

 

获取SqlSessionFactory工厂对象的功能类。

 // 通过构建的方式构建了一个SqlSessionFactory
         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
 ​
 //xxxBuilder.build()

2.3 SqlSessionFactory

org.apache.ibatis.session.SqlSessionFactory:获取 SqlSessi 对象的工厂接口。

SqlSession openSession() 获取SqlSession对象,并开启手动提交事务

SqlSession openSession(boolean autoCommit) 获取SqlSession对象,true表示自动提交

 

2.4SqlSession

org.apache.ibatis.session.SqlSession:sql会话对象接口。用于执行SQL管理事务接口代理

   
void commit() 提交事务
void rollback() 回滚事务
T getMapper(Class cls) 获取指定接口的代理实现类对象
void close() 释放资源

3. 映射配置文件

编码完成如下需求:


1 // 需求1:查询id为1的学生(强制要求)
2 // 需求2:创建一个Student对象并保存到数据库(参数和成员变量名保持一致)(成功了吗?)
3 // 需求3:根据学生姓名和年龄查询用户,传两个参数(多个参数怎么办?)
4 // 需求4:完成需求3,传一个参数。

 

映射配置文件StudentDao.xml保证这个文件的名字和接口名完全一致,且在同一个包下。

View Code

 

 

核心配置文件

1  <!-- 加载映射配置文件  这里使用的是/ -->
2  <mappers>
3      <mapper resource="com/itheima/dao/StudentDao.xml"/>
4  </mappers>

 

 

Dao层接口StudentDao

 1 public interface StudentDao {
 2     @Select("select * from student where  id = 1")
 3     Student findById();
 4 
 5     // 需求1:查询id为1的学生(强制要求)
 6     Student findById2(@Param("id") Integer id);
 7 
 8     // 需求2:创建一个Student对象并保存到数据库
 9     void save(Student stu);
10 
11     // 需求3:根据学生姓名和年龄查询用户,传两个参数(多个参数怎么办?)
12     List<Student> findByNameAndAge(@Param("name") String name, @Param("agex") Integer age);
13 
14     // 需求4:完成需求3,传一个参数。
15     // 4.1 把两个参数封装成一个实体对象
16     // 如果把多个参数封装到一个实体对象中,参数类型有局限性,不能是两个一样的条件做范围查询
17     List<Student> findByStudent(Student stu);
18 
19     // 4.2 把两个参数封装到Map集合中
20     List<Student> findByMap(Map<String,Object> map);
21 }

 

 

测试类

 1 /**
 2  * @Author sonyan
 3  * @Date 2020/8/7 11:19
 4  * @Description: 测试类
 5  */
 6 public class MybatisDemo {
 7     public static void main(String[] args) throws Exception {
 8 
 9         // 指定核心配置文件
10         String resource = "mybatis-config.xml";
11         // 把核心配置文件加载成流  Resources为我们提供的方便读取配置文件的工具类
12         InputStream inputStream = Resources.getResourceAsStream(resource);
13 
14         // 通过构建的方式构建了一个SqlSessionFactory
15         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
16 
17         // SqlSession 就相当于我们之前的 Connection
18         // JDK7新特性  try-with-resource
19         // 需要释放资源的动作,自动释放在try()中开启的一些流、会话......
20         try (SqlSession session = sqlSessionFactory.openSession(true)) {
21 
22             // getMapper  getDao   获取一个指定接口的实现类对象
23             // 底层是动态代理
24             // 动态代理可以增强有接口的类、接口(增强接口,就是现实接口)
25             // 就相当于我们自己new StudentDaoImpl();
26             // 这个StudentDaoImpl是Mybatis通过动态代理帮我们自动生成并且赋值给了studentDao
27             StudentDao studentDao = session.getMapper(StudentDao.class);
28 
29             /*List<Student> students = studentDao.findAll();
30             System.out.println("students = " + students);*/
31 
32 
33             // 测试根据id查询
34             /*Student student = studentDao.findById(1);
35             System.out.println("student = " + student);*/
36 
37             // 测试添加学生
38             //studentDao.saveStudent(new Student(null,"凤姐",20));
39 
40             // 根据名称和年龄查询用户,参数是两个基本类型
41             //List<Student> students = studentDao.findByNameAndAge("美女", 20);
42             //System.out.println("students = " + students);
43 
44             // 根据名称和年龄查询用户,参数是一个student对象
45             //List<Student> students = studentDao.findByUser(new Student(null, "凤姐", 20));
46             //System.out.println("students = " + students);
47 
48             // 根据名称和年龄查询用户,参数是一个map集合
49 
50             HashMap<String, Object> map = new HashMap<>();
51             map.put("name", "王二蛋");
52             map.put("age", 20);
53 
54             System.out.println("studentDao.findByMap(map) = " + studentDao.findByMap(map));
55 
56 
57             // 手动提交
58             //session.commit();
59 
60             // session.close();
61         }
62 
63     }
64 }

 

 

4. 核心配置文件

4.1 properties(重要)

引入外部的properties文件,一般用作引入数据库链接参数的配置。

核心配置文件

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <!-- 这是一个mybatis的核心配置文件,名字任意-->
 6 <configuration>
 7     <!-- -->
 8     <properties resource="jdbc.properties"/>
 9 
10     <environments default="development">
11         <environment id="development">
12             <transactionManager type="JDBC"/>
13             <dataSource type="POOLED">
14                 <property name="driver" value="${jdbc.driver}"/>
15                 <property name="url" value="${jdbc.url}"/>
16                 <property name="username" value="${jdbc.username}"/>
17                 <property name="password" value="${jdbc.password}"/>
18             </dataSource>
19         </environment>
20     </environments>
21 
22     <!-- 加载映射配置文件 -->
23     <mappers>
24         <mapper resource="com/itheima/dao/StudentDao.xml"/>
25     </mappers>
26 </configuration>

 

jdbc.properties

1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://192.168.115.130:3306/db1
3 jdbc.username=root
4 jdbc.password=root

 

 

4.2 Settings(重要)

 1 <!-- 极为重要的设置 -->
 2 <settings>
 3     <!--
 4         指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
 5         LOG4J  要求:1. 导入log4j的jar包  2. 有一个log4j.properties文件
 6         建议显式的配置上。可配可不配的,建议配上。
 7      -->
 8     <setting name="logImpl" value="LOG4J"/>
 9 
10 
11     <!--
12         mapUnderscoreToCamelCase
13         是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
14 
15         Java中多个单词的属性名  使用驼峰命名   lastName
16         MySQL不缺分大小写      底杠命名       last_name
17 
18 
19         Mybatis可以帮我们自动完成结果集和实体的自动转换封装,原因是结果集的字段名和实体属性名一致。
20 
21     -->
22     <!--<setting name="mapUnderscoreToCamelCase" value="true"/>-->
23 </settings>

 

 

4.3 TypeAliases(了解)

 1 <!-- 起别名 -->
 2 <typeAliases>
 3     <!--
 4         type 全限定类名
 5         alias 别名
 6         别名不区分大小写
 7      -->
 8     <!--<typeAlias type="com.itheima.domain.Student" alias="student"/>-->
 9 
10     <!-- 为包下所有的实体类起别名,不区分大小写 -->
11     <!--<package name="com.itheima.domain"/>-->
12 
13 </typeAliases>

 

起别名后,在映射配置文件中可以直接使用别名

1 <select id="findByMap" resultType="Student">
2        select * from student where first_username=#{name}
3        and
4        age=#{age}
5 </select>
6  

 

系统为常见的类型起好了别名

4.4 Environments(了解)

 1 <environments default="dev">
 2     <environment id="dev">
 3         <transactionManager type="JDBC"/>
 4         <dataSource type="POOLED">
 5             <!-- 连接数据库四要素 -->
 6             <property name="driver" value="${jdbc.driver}"/>
 7             <property name="url" value="${jdbc.url}"/>
 8             <property name="username" value="${jdbc.username}"/>
 9             <property name="password" value="${jdbc.password}"/>
10         </dataSource>
11     </environment>
12     <environment id="test">
13         <transactionManager type="JDBC"/>
14         <dataSource type="POOLED">
15             <!-- 连接数据库四要素 -->
16             <property name="driver" value="${jdbc.driver}"/>
17             <property name="url" value="${jdbc.url}"/>
18             <property name="username" value="${jdbc.username}"/>
19             <property name="password" value="${jdbc.password}"/>
20         </dataSource>
21     </environment>
22 </environments>

 

 

4.5 Mappers(重点)

 1 <!-- 加载映射配置文件 -->
 2 <mappers>
 3     <!--
 4         使用相对于类路径的资源引用 可以用
 5         每个标签引入一个Mapper的XML文件
 6      -->
 7     <!--<mapper resource="com/itheima/dao/StudentDao.xml"/>-->
 8     <!--<mapper resource="com/itheima/dao/CourseDao.xml"/>-->
 9     <!--<mapper resource="com/itheima/dao/OrderDao.xml"/>-->
10 
11     <!--
12         使用完全限定资源定位符(URL) 不推荐使用
13         http://   file://
14      -->
15     <!--<mapper url="file:///var/mappers/AuthorMapper.xml"/>-->
16 
17     <!--
18         加载指定某个的接口,识别接口中的注解 可以用
19      -->
20     <!--<mapper class="com.itheima.dao.StudentDao"/>-->
21     <!--<mapper class="com.itheima.dao.StudentDao"/>-->
22     <!--<mapper class="com.itheima.dao.StudentDao"/>-->
23 
24     <!--
25         把包下所有的映射配置文件和接口全部加载进来  最推荐使用
26      -->
27     <package name="com.itheima.dao"/>
28 </mappers>
29  

 

 

 

 

 

5. 经验分享

5.1 生成Mybatis配置文件

本质是新建了一个文件模板,按照下面的方式新建两个模板即可(Mybatis-configMybatis-Mapper

 

 

 

 

5.2 接口映射配置文件跳转

使用一个插件free-idea-mybatis

这个插件是个zip包,不要解压,直接安装即可。

已知bug:

多个模块之间有相同内容会提示/跳转错误,卸载其他模块即可。

 

5.3 ${}和#{}区别(面试题)

##{} MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法

${} 会做字符串的拼接,将{}中直接拼直接在 SQL 语句中,可能会有SQL注入的风险,效率更低。但是,如果你需要在SQL语句中直接插入一个不转义的字符串,可以使用这种方式。一般情况下会把表名或者字段名通过这方方式传递到SQL语句中,比方说 ORDER BY后面的列名。

 

5.4 MybatisUtils工具类抽取

 1 public class MybatisUtills {
 2 
 3     // 获取工厂对象SQLSessionFactory,这个对象一个就可
 4     private static SqlSessionFactory ssf = null;
 5 
 6     // 静态代码块中初始化该对象
 7     static {
 8         InputStream is = null;
 9         try {
10             is = Resources.getResourceAsStream("MyBatisConfig.xml");
11         } catch (IOException e) {
12             e.printStackTrace();
13         }
14         ssf = new SqlSessionFactoryBuilder().build(is);
15     }
16 
17     public static SqlSessionFactory getFactory() {
18         return ssf;
19     }
20 
21 
22     // 获取SQLSession对象,这个连接对象可以有多个
23     public static SqlSession getSqlSession() {
24         return ssf.openSession(true);
25     }
26 
27 
28     // 获取Mapper对象
29     public static <T> T getMapper(Class<T> tClass) {
30         return ssf.openSession(true).getMapper(tClass);
31     }
32 
33 }

 

posted @ 2020-10-10 21:28  sonyan  阅读(213)  评论(0编辑  收藏  举报