MyBatis框架笔记1

目录

1、什么是MyBatis

2、搭建MyBatis项目

3、Maven

           安装配置

           新建Maven项目

4、MyBatis开发步骤

           (1)配置依赖

           (2)新建和配置mybatis配置文件

           (3)编写实体类

           (4)配置映射文件

           (5)编写代码

5、实现CRUD

            (1)插入操作:保存学校

            (2)根据编号查询学校

            (3)修改学校信息

            (4)根据学校编号删除

            (5)其他

6、${} 和 #{}

7、配置文件

          (1)properties(属性)

          (2)environment(环境变量)

8、Mapper接口方式

            第一步:定义接口

            第二步:编写映射文件

            第三步:编写业务层代码

9、结果映射

            普通属性映射配置

            特别注意

10、关联映射 ?????

            实现方式


1、什么是MyBatis

MyBatis是一款 优秀的 ORM 持久层 框架,用于简化版JDBC开发

  • ORM

    • Object - Relational - Mapping

    • 即 Java对象(类)- 关系型数据库(表)- 映射配置

    • 用来映射 类名和表名、属性和字段、Java类型和数据库类型等信息

  • 持久层

    • 瞬时状态转为持久状态过程---包括 插入、更新、删除等操作

    • 持久状态转为瞬时状态过程---包括 查询操作

    • 持久化:瞬时状态和持久状态相互转化的过程,称之为持久化

    • 负责将数据保存到数据库的那一层代码

    • JavaEE三层架构:表现层、业务层、持久层

  • 序列化

    • ObjectinputStreame 和 ObjectoututStreame

    • 把对象状态转换为可存储或可传输的状态,称之为序列化

    • 把可存储或可传输的状态转换为对象状态,称之为反序列化

  • 框架

    • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型

    • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展

2、搭建MyBatis项目

准备工作:

  • 创建数据库和表

  • Maven

    • 传统 Web项目,把jar包手动拷贝到WEB-INF/lib

      • jar多

      • 版本不一致

    • Maven Web项目,只需配置pom.xml即可,自动下载、导入和管理jar包

3、Maven

Maven 是一款优秀Java自动构建工具

  • 源码 - 编译 - 测试 - 部署 - 安装等 到服务器

  • 同类:Ant、Gradle

安装配置

  • 下载:Maven官网

  • 配置:

    • 解压到非中文目录下

    • 配置 Maven_Home 安装目录下的conf目录下的settings.xml配置文件,配置本地仓库的目录

      • 例如本电脑:D:\maven\apache-maven-3.6.1\conf\settings.xml

      • 本地仓库:存放bar包的位置目录

        <localRepository>D:\maven\apache-maven-3.6.1\maven_repository</localRepository>

    • 在 idea 开发工具中配置自定义的 Maven 目录

      • File - Settings - 搜索 Maven 进行配置,如下图:

      • 注意:为了防止新建工程时,又重新恢复到默认,建议配置“新建项目设置”,可永久保存

      • 配置阿里云镜像

        问题:每次在下载第一次使用的jar时,都会去访问中央仓库 国外的服务器,速度相对较慢

        所以为了提高下载速度,我们可以修改默认下载服务器的url,更换为阿里云服务器

新建Maven项目

  • File - New Project - Empty Project

  • 新工程下右键,new Module 选择 Maven

  • 注意:新的Maven目录

    • 约定大于配置

    • 源代码文件:src/main/java

    • 资源文件位置:src/main/resources

    • 测试代码目录:src/test/java

  • 自动化和半自动化

    • 自动化代表Hibernate,半自动化代表Mybatis

    • 自动化的优点 开发效率高,代码量小,不需要学习SQL,缺点 缺失灵活性

    • 半自动化优点 灵活性高运行效率相对较高,省略了自动生成SQL的过程,缺点 开发效率相对较低,代码量大,需要血虚SQL

4、MyBatis开发步骤

(1)配置依赖

在pom.xml中配置 mysql 驱动依赖和 mybatis 依赖

 <dependencies>
 ​
  <!--mysql 驱动-->
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
  </dependency>
 ​
  <!--mybatis 依赖-->
  <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
  <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.10</version>
  </dependency>
 ​
 </dependencies>

(2)新建和配置mybatis配置文件

  • 可以通过官网拷贝mybatis – MyBatis 3 | 入门

  • 位置:在 src/main/resources 下新建 mybatis_config.xml(名字可以自己定义)

     <?xml version="1.0" encoding="UTF-8" ?>
     <!DOCTYPE configuration
             PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
             "https://mybatis.org/dtd/mybatis-3-config.dtd">
     <configuration>
         <environments default="developmentA">
             <environment id="developmentA">
                 <transactionManager type="JDBC"/>
                 <dataSource type="POOLED">
                     <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                     <property name="url" value="jdbc:mysql://127.0.0.1:3306/school"/>
                     <property name="username" value="root"/>
                     <property name="password" value="root"/>
                 </dataSource>
             </environment>
            <!-- <environment id="developmentB">
                 <transactionManager type=""></transactionManager>
                 <dataSource type=""></dataSource>
             </environment>-->
         </environments>
         <mappers>
             <mapper resource="mapper/SchoolMapper.xml"/>
         </mappers>
     </configuration>

(3)编写实体类

  • 和表结构对应

  • 可以使用 Lombok 简化 setter 和 getter

 @Data
 public class School {
     private Integer scid;
     private String scname;
     private String address;
 }

(4)配置映射文件

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.adada.dao.MySpace">
     <select id="getCount">
         select count(*) from school
     </select>
 </mapper>

注意:还要更新配置文件,配置关联

<mappers>
     <mapper resource="mapper/SchoolMapper.xml"/>
 </mappers>

(5)编写代码

SqlSessionFactoryBuilder

SqlSessionFactory

SqlSession

 public class TestMyBatis {
     public static void main(String[] args) {
         //解析 xml 配置和映射文件
         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
         try {
             InputStream is = Resources.getResourceAsStream("mybatis_config.xml");
             //创建SqlSessionFactory
             SqlSessionFactory sqlSessionFactory= builder.build(is);
             //创建SqlSession
             SqlSession sqlSession= sqlSessionFactory.openSession();
             //执行SQL
             Integer count = sqlSession.selectOne("com.adada.dao.MySpace.getCount");
 ​
             System.out.println(">>>>>>"+count);
             //关闭
             sqlSession.close();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }

5、实现CRUD

为了简化获取session,先封装工具类MyBatisUtil

 public class MyBatisUtil {
  private static String configFile = "mybatis_config.xml";
 ​
  private static SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
  private static SqlSessionFactory sqlSessionFactory;
 ​
  static {
      sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
 ​
      InputStream resourceAsStream = null;
      try {
          resourceAsStream = Resources.getResourceAsStream(configFile);
      } catch (IOException e) {
          e.printStackTrace();
      }
      sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
 ​
  }
 ​
  /*
     * 默认是true
     */
     public static SqlSession getSqlSession() {
         return getSqlSession(true);
 ​
     }
     public static SqlSession getSqlSession(boolean commit) {
         return sqlSessionFactory.openSession(commit);
     }
     public static void close(SqlSession session){
         if (session!=null){
             session.close();
         }
     }
 }

(1)插入操作:保存学校

  • 修改映射文件,新增<insert>节点

     <!--insert-->
     <insert id="saveSchool" parameterType="com.adada.pojo.School">
         insert into school(scid,scname,address)values
                (#{scid},#{scname},#{address})
     </insert>
  • 调用

     public class TestInsert {
         public static void main(String[] args) {
             SqlSession session = MyBatisUtil.getSqlSession();
             //封装实体类
             School school = new School();
             school.setScid(5);
             school.setScname("金台高中");
             school.setAddress("群众路");
     ​
             //保存
             int rows = session.insert("saveSchool", school);
             System.out.println(rows);
     ​
             //关闭
             MyBatisUtil.close(session);
         }
     }
  • 注意:

    为了方便调试,最好在执行过程中能显示打印执行的日志信息,可以通过配置文件,配置开启日志功能 -- 打印Sql语句

     <settings>
         <!--日志配置-->
         <setting name="logImpl" value="STDOUT_LOGGING"/>
     </settings>

(2)根据编号查询学校

  • 修改映射文件,新增查询节点

     <!--select-->
     <!--根据主键查询明细-->
     <select id="getSchoolById" resultType="school">
         select scid,scname,address from school where scname=#{scname}
     </select>
  • 注意别名:为了简化实体类写法,可以在配置文件中配置别名

      <typeAliases>
             <!--配置一个实体类的别名,且不区分大小写-->
     <!--        <typeAlias type="com.adada.pojo.School" alias="school"></typeAlias>-->
             <!--配置包下所有类别名,在映射文件中,默认在此包下载实体类-->
             <package name="com.adada.pojo"/>
         </typeAliases>
  • 编写代码调试

     public class TestSelect {
         public static void main(String[] args) {
             SqlSession session= MyBatisUtil.getSqlSession();
             School school=session.selectOne("getSchoolById",2);
             System.out.println(school);
     ​
             MyBatisUtil.close(session);
         }
     }

(3)修改学校信息

  • 修改映射文件,新增<update>标记元素

  • 先查询 在修改

映射文件:

<!--根据用户编号,修改学校信息-->
 <update id="updateSchool" parameterType="school">
     update school set scname=#{scname},address=#{address}
     where scid=#{scid}
 </update>

代码:

 public class TestUpdate {
     public static void main(String[] args) {
         SqlSession session= MyBatisUtil.getSqlSession();
 ​
         School school=session.selectOne("getSchoolById",2);
         school.setScid(2);
         school.setAddress("新建路");
 ​
         session.update("updateSchool",school);
     }
 }

(4)根据学校编号删除

  • 修改映射文件,新增<delete>标记元素

     <delete id="delSchool">
         delete from school where scid=#{scid}
     </delete>
  • 代码:

     public class TestDelete {
         public static void main(String[] args) {
             SqlSession session= MyBatisUtil.getSqlSession();
     ​
             int rows = session.delete("delSchool", 5);
             System.out.println(rows);
     ​
             MyBatisUtil.close(session);
         }
     }

(5)其他

useGeneratedKeys的用法

  • 作用:插入时,自动获取主键

场景描述:

需要同时新增新的老师,并新增老师属于此学校,所以需要保存学校后,直接获取到老师编号

   SqlSession session = MyBatisUtil.getSqlSession();
 ​
   //新增老师同时新增学校
   Teacher teacher=new Teacher();
   teacher.setSname("李四");
   //保存部门
   session.insert("save",teacher);
   System.out.println(">>>>>老师编号:"+teacher.getSid());
 ​
 ​
 ​
   //封装实体类
   School school = new School();
 //        school.setScid(5);
   school.setScname("金台高中");
 //        school.setAddress("群众路");
   school.setScid(teacher.getSid());
 ​
   //保存
   int rows = session.insert("saveSchool", school);

默认情况下,上面的老师编号为null。

解决办法:在映射文件的<insert>标记中添加两个必须的属性 useGeneratedKeys="true" keyProperty="sid"

 <insert id="save" parameterType="teacher" useGeneratedKeys="true" keyProperty="sid" keyColumn="sid">
  insert into teacher(sname) values (#{sname})
 </insert>

这样,再次执行上面的代码,老师的编号就有值了

复用SQL

  • 先把公共部分,提取到<sql>标记中,并指定id编号,如:

 <!--复用Sql:公共的片段,单独编写到 Sql 元素中-->
 <sql id="schoolCols">
     scid,scname,address
 </sql>
  • 在需要使用公共部分的位置,引用<include>标记元素,如:

 <select id="queryAll" resultType="school">
     select 
     <include refid="schoolCols"></include>
     from school
 </select>

6、${} 和 #{}

在映射文件中引用传参时,可以同时使用 ${} 和 #{}

例如:实现学校的多条件查询,可以根据学校的名字和地址来做查询

  • 修改映射文件,新增下面代码:

     <!--根据学校名字和地址 多条件查询-->
     <select id="querySchool" resultType="school">
         select scid,scname,address from school
         where scname=#{scname} and address='${address}'
     </select>

注意:上面的${address}必须带单引号的

  • 上面配置使用了 #{} 和 ${} 生成的SQL如下:

    => Preparing: select scid,scname,address from school where scname=? and address='渭工路' => Parameters: 新福园(String) <= Total: 0

区别:

${} 用来拼接SQL语句时,使用时注意对于字符型,手动添加单引号。缺点:不安全,可能引起SQL注入安全问题

#{} 先生成带占位符?的语句,再给占位符赋值。优点:类型处理自动判断识别,灵活且安全

在注意:

如果传入多个参数,除了可以使用实体类之外,还可以使用Map来传参

 public static void main(String[] args) {
     SqlSession session= MyBatisUtil.getSqlSession();
 ​
     Map<String,Object> param=new HashMap<>();
     param.put("scname","新福园");
     param.put("address","渭工路");
 ​
     List<School> list=session.selectList("querySchool",param);
     list.forEach(System.out::println);
 }

7、配置文件

配置文件中常用的元素:

(1)properties(属性)

可以通过此标记中的属性引用外部的属性配置文件,键值对的属性资源文件。

引用之前,要先新建db.properties,并编辑好内容

新建db.properties文件

 username=root
 password=root
 url=jdbc:mysql://127.0.0.1:3306/school
 driver=com.mysql.cj.jdbc.Driver

在配置文件中的使用:

<properties resource="db.properties">
     <!-- 用作默认值,如果属性文件中获取不到对应属性时,这里才会起作用,优先级低于属性文件的-->
     <property name="password" value="root"/>
 </properties>

注意:

在配置文件的属性设置中 <property name="password" value="root"/>优先级低于属性资源配置文件,所以我们一般把配置文件中的属性设置为默认值。

使用属性文件中的配置信息:

 <environment id="developmentA">
     <transactionManager type="JDBC"/>
     <dataSource type="POOLED">
         <property name="driver" value="${driver}"/>
         <property name="url" value="${url}"/>
         <property name="username" value="${username}"/>
         <property name="password" value="${password}"/>
     </dataSource>
 </environment>

(2)environment(环境变量)

在配置文件中

事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(两种取值也就是 type="[JDBC|MANAGED]")

数据源(dataSource)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")

8、Mapper接口方式

在多层架构开发中,我们常常按功能划分为控制层、业务层、Dao层

在Dao层中,一般都会设计接口来访问数据库

第一步:定义接口

IShoolDao接口

 /*
 * 接口---特殊的抽象类---高度抽象类---接口
 * 抽象---复杂问题简单化---具体实现接口
 * 接口---定义规范
 * */
 public interface ISchoolDao {
 ​
     void save(School school);
 ​
     void delete(School school);
 ​
     void update(School school);
 ​
     School get(Integer scid);
 ​
     List<School> queryAll();
 ​
 }

第二步:编写映射文件

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <!-- 1.要求:命名空间必须和dao的接口保持一致,取值只能是接口的完整类名
             因为可以把这里的映射文件理解成Dao接口的实现类
 -->
 <mapper namespace="com.adada.dao.ISchoolDao">
     <!-- 就是ISchoolDao接口中get方法的实现 -->
     <select id="get" resultType="school">
         select scid,scname,address from school where scid=#{scid}
     </select>
 ​
     <select id="queryAll" resultType="school">
         select scid,scname,address from school
     </select>
 </mapper>

注意:

  • namespace命名空间取值,必须是接口的完整限定名(全类名)

  • 编写sql的标记元素id取值必须和接口名要实现的方法名保持一致

  • 标记元素id的实现不需要和接口完全一致,比如:可以实现部分sql方法,可以额外增加其他名字的sql标记

第三步:编写业务层代码

通过sqlSession.getMapper() 方式获取对应接口的代理对象

 /*
 * Mapper 代理接口方式实现
 * */
 public class SchoolService {
     public static void main(String[] args) {
 ​
         //获取sqlSession
         SqlSession sqlSession= MyBatisUtil.getSqlSession();
         //动态代理 动态根据代理实现生成对应的实现类代理对象
         ISchoolDao dao=sqlSession.getMapper(ISchoolDao.class);
 ​
         //根据编号查询
         School school= dao.get(1);
         //查询所有学校
         dao.queryAll().forEach(System.out::println);
 ​
         System.out.println(school);
     }
 }

9、结果映射

当查询的 SQL 中,出现了表字段名和实体类属性名不一致情况时,需要指定映射关系

常见方式:

  • 使用 SQL 的 AS 别名方式

  • ResultMap 方式

普通属性映射配置

第一步:编写结果映射

<!-- 结果映射 -->  
     <resultMap id="schoolMap" type="school">
         <id property="scid" column="scid"></id>
         <result property="scname" column="scname"></result>
         <!-- 如果属性名和字段名一致时,可以省略掉 -->
 <!--        <result property="address" column="address"></result>-->
     </resultMap>

第二步:<select> 查询中引用

 <!-- 使用结果映射,就是把 resultType 换成 resultMap,注意两者不能同时使用-->
 <select id="queryAll" resultMap="schoolMap">
     select scid,scname,address from school
 </select>

第三步:代码查询,检查不一致的属性是否能获取到值

 //获取sqlSession
 SqlSession sqlSession= MyBatisUtil.getSqlSession();
 //动态代理 动态根据代理实现生成对应的实现类代理对象
 ISchoolDao dao=sqlSession.getMapper(ISchoolDao.class);
 ​
 //根据编号查询
 School school= dao.get(1);
 //查询所有学校
 dao.queryAll().forEach(System.out::println);

特别注意

autoMapping

此属性属于映射文件中 resultMap 标记

如果设置这个属性,MyBatis将会为本结果映射开启或关闭自动映射

这个属性会覆盖全局属性 autoMappingBehavior。默认值:true

如果是false,只是映射在<resultMap>中配置的属性才会被映射

     <resultMap id="schoolMap" type="school" autoMapping="true">
         <id property="scid" column="scid"></id>
         <result property="scname" column="scname"></result>
         <!-- 如果属性名和字段名一致时,可以省略掉 -->
 <!--        <result property="address" column="address"></result>-->
     </resultMap>

如果要设置所有的结果映射中的行为策略为默认禁用自动映射,可以在配置文件中在配置下面的配置

autoMappingBehavior

此属性属于配置文件中 settings 标记下的配置

指定 MyBatis 应如何自动配置列到字段或属性。

  • NONE 表示禁用全部的自动配置

  • PARTIAL 只会自动映射没有定义嵌套结果映射的字段

  • FULL 会自动映射任何复杂的结果集

 <settings>
     <setting name="autoMappingBehavior" value="PARTIAL"/>  <!-- NONE 禁用全部的自动配置,PARTIAL 默认-->
 </settings>

注意:

如果配置了 autoMappingBehavior 为 NONE 时,会对其他没有使用结果映射的查询结果产生影响

对没有使用结果映射,而使用 resultType 的查询,会查询结果直接为null。

例如:

配置文件中配置:

<setting name="autoMappingBehavior" value="NONE"/>  

映射文件中:

     <resultMap id="schoolMap" type="school" autoMapping="true">
         <id property="scid" column="scid"></id>
         <result property="scname" column="scname"></result>
     </resultMap>
 ​
     <!-- 下面使用 resultType,代码调用查询结果返回的 school 对象为null -->
     <select id="get" resultType="school">
         select scid,scname,address from school where scid=#{scid}
     </select>
 ​
     <!-- 下面使用 resultMap,可以有正常的映射结果 -->
     <select id="queryAll" resultMap="schoolMap">
         select scid,scname,address from school
     </select>

10、关联映射 ?????

通过一个对象的查询,可以很方便的自动关联查询其他对象

一对一

一对多

多对多

实现方式

实现方式:

1.内嵌查询:发起N+1查询

2.内嵌映射

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值