mybatis入门

如何外部导入jar包

外部加载引入jar包:(jar文件夹不能发生改变或者删除,好处只需往这个文件里面加入jar包项目就可以自动加载jar包,无需另外的导入)

导入的过程和mybatis的项目结构

mybatis项目项目架构(这里建立的是java项目)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
建立放置配置文件的包

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

mybatis的简介

MyBatis,实质上 Mybatis 对 ibatis 进行一些改进。

MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消 除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录。

Mybatis是一个orm框架(Object relation Mapping),持久层技术,支持动态sql调用,存储过程调用(数据库编程 for if in out),sql和java代码显示分离。(高内聚 低耦合)提高程序的扩展性和维护性。

mybatis的执行流程

在这里插入图片描述

分析:

1.mybatis 配置文件,包括 Mybatis 全局配置文件和 Mybatis 映射文件,其中全局配 置文件配置了数据源、事务等信息;映射文件配置了 SQL 执行相关的信息。

2.mybatis 通过读取配置文件信息(全局配置文件和映射文件),构造出 SqlSessionFactory,即会话工厂。

\3. 通过 SqlSessionFactory,可以创建 SqlSession 会话。Mybatis 是通过 SqlSession 来操作数据库的。

4.SqlSession 本身不能直接操作数据库,它是通过底层的 Executor 执行器接口来操作数据库的。Executor 接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。

Executor 执行器要处理的 SQL 信息是封装到一个底层对象 MappedStatement 中。该对 象包括:SQL 语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果 的映射类型包括 java 的简单类型、HashMap 集合对象、POJO 对象类型。

看到 Mybatis 的框架图,可以清晰的看到 Mybatis 的整体核心对象,用图来表达 Mybatis 的整个的执行流程。如下图所示:

在这里插入图片描述

原理详解:

MyBatis 应用程序根据 XML 配置文件创建 SqlSessionFactory,SqlSessionFactory 再根据配置,配置来源于两个地方,一处是配置文件,一处是 Java 代码的注解,获取一 个 SqlSession。SqlSession 包含了执行 sql 所需要的所有方法,可以通过 SqlSession 实例直接运行映射的 sql 语句,完成对数据的增删改查和事务 交等,用完之后关闭 SqlSession。

环境搭建

1: 引入当前框架的主体结构(***.jar)

mybatis.jar: mybatis 的核心包

mysql.jar: 驱动包

log4j……jar: 日志工具包

及mydatis相关的依赖包

2: 数据库新建表并添加测试数据

3.创建项目,建立相应目录文件

4.建立实体类

public class Person  implements Serializable {
    private int id;
    private String name;
    private Date bir;
    private String address;

5: mybatis-config.xml 编写

​ Mybatis的环境配置:

​ 事务配置 数据源配置 加载mapper.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>
    <!--起别名-->
    <typeAliases>
        <!-- 直接扫描实体类的包,在mapper.xml使用到全路径的实体类直接写实体类的名 -->
        <package name="com.study.homework.entity"/>
    </typeAliases>


    <environments default="development">
        <!--  开发的环境 -->
        <environment id="development">
            <!--  事务控制  JDBC事务管理 -->
            <transactionManager type="JDBC"/>
            <!--  数据库 连接池的技术-->
            <dataSource type="POOLED">
              <!--  <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/user_db?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="admin"/>-->
                
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--  加载外部的配置文件 : mapper接口和接口方法的映射 -->
    <mappers>
        <mapper resource="com/study/homework/mapper/StudentMapper.xml"/>
    </mappers>
</configuration>
  1. 日志log4j.properties的配置

    log4j.rootLogger=DEBUG, stdout
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    
    

数据库配置文件:db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/user_db?characterEncoding=utf-8
jdbc.username=root
jdbc.password=admin

7配置mapper.xml

​ 1)构建一个mapper接口(定义操作数据库的方法)

package com.study.homework.mapper;

import com.study.homework.entity.Student;

import java.util.List;

public interface StudentMapper {
    /*    1、查看所有学员信息
    2、按姓名查看学员信息(学员可同名)
                3、按id查看学员信息
    4、新增学员信息
    5、通过id删除学员信息
    6、通过id修改学员信息
    7、统计班级人数*/
    List<Student> studentAll();//查看所有学员信息

    List<Student> studentByName(String name);//按姓名查看学员信息(学员可同名)

    Student seleteById(int id);//按id查看学员信息

    int insertStudent(Student student);//新增学员信息
//如果这里是用来integer类型,xml配置文件里面的参数类型就要使用integer的全路径加类名
    int deleteStudentById(int id);//通过id删除学员信息

    int updateStudentById(Student student);//通过id修改学员信息

    int countStudent();//统计班级人数
}

2)定义一个和接口名称相同的配置文件***Mapper.xml

注意:Namespace: 必须和我们mapper接口全部限定名称一致的

各种操作标签 : insert delete update select

<?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.study.homework.mapper.StudentMapper">
    <!--    查询所有  -->
    <select id="studentAll" resultType="Student">
        select * from student
    </select>
    <!--    按照条件查询-->
    <select id="studentByName" parameterType="string" resultType="Student">
        select * from student where name=#{name}
    </select>
    <!--    按照id查询-->
    <select id="seleteById" parameterType="int" resultType="Student">
        select * from student where name=#{id}
    </select>
    <insert id="insertStudent" parameterType="Student">
        INSERT INTO `student`(`name`, `sex`, `age`, `address`, `tel`, `email`)
         VALUES ( #{name}, #{sex}, #{age}, #{address}, #{tel}, #{email});
    </insert>
      <!--执行单元
    添加   insert
       id:对应接口的方法名     实现哪个方法
       parameterType:参数类型    自定义类,完全限定名
       返回值类型,一般可以不用写   insert,update,delete默认返回值类型为int
       读取参数对象中的属性:#{属性名}
       -->
 <!--参数类型:这里面的id或者其他是这个对象的成员名-->
    <update id="updateStudentById" parameterType="Student">
update student SET `name` = #{name}, sex = #{sex}, age = #{age},
address = #{address}, tel = #{tel}, email = #{email} WHERE id = #{id};
    </update>
    <!--参数类型:#{id}这个id是接口方法写的参数名-->
    <delete id="deleteStudentById" parameterType="int">
        delete from student where id=#{id}
    </delete>
    <select id="countStudent" resultType="int">
        select count(*) from student;
    </select>
</mapper>

8: 创建测试类(这是另外一个实体类的测试)

public class App {

    @Test
    public void testSave(){
        //加载全局置文件
        String fileName="mybatis-config.xml";
        try {
            //Resources是mybatis中提供的一个工具类
            InputStream inputStream = Resources.getResourceAsStream(fileName);
            //创建工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过工厂拿到一个会话
            try (SqlSession sqlSession = factory.openSession()) {
                //通过反射拿到接口
                PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
                Person person=new Person(0,"张三直",new Date(),"广东");
                int result = mapper.save(person);
                //提交事务    增删改
                sqlSession.commit();
                sqlSession.close();
                if(result>0){
                    System.out.println("添加成功");
                }else{
                    System.out.println("添加失败");
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testUpdate(){
        //加载全局置文件
        String fileName="mybatis-config.xml";
        try {
            //Resources是mybatis中提供的一个工具类
            InputStream inputStream = Resources.getResourceAsStream(fileName);
            //创建工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过工厂拿到一个会话
            try (SqlSession sqlSession = factory.openSession()) {
                //通过反射拿到接口
                PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
                Person person=new Person(6,"张六",new Date(),"广东");
                int result = mapper.update(person);
                //提交事务    增删改
                sqlSession.commit();
                sqlSession.close();
                if(result>0){
                    System.out.println("修改成功");
                }else{
                    System.out.println("修改失败");
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testRmove(){
        //加载全局置文件
        String fileName="mybatis-config.xml";
        try {
            //Resources是mybatis中提供的一个工具类
            InputStream inputStream = Resources.getResourceAsStream(fileName);
            //创建工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过工厂拿到一个会话
            try (SqlSession sqlSession = factory.openSession()) {
                //通过反射拿到接口
                PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);

                int result = mapper.remove(8);
                //提交事务    增删改
                sqlSession.commit();
                sqlSession.close();
                if(result>0){
                    System.out.println("修改成功");
                }else{
                    System.out.println("修改失败");
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//无关的测试但是有注释
 @Test
    public void updateText(){
        try {
            //定义配置文件路径,这里默认是从resource开始,以resource作为根目录
            String fileName = "mybatis-config.xml";//实际的文件目录地址如果resource下直接写文件名但是不能在前面加/
            InputStream resource = Resources.getResourceAsStream(fileName);//获取全局配置文件的字节流对象
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resource);//获取sqlsession工厂
            SqlSession sqlSession = build.openSession();//获取sqlsession对象获取操作数据的方法
            PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);//通过反射获
            Person person=new Person();
            person.setId(2);
            person.setAddress("上海");
            person.setBir(new Date());
            person.setName("火影");
            int i = mapper.update(person);//取接口对象的方法
            sqlSession.commit();//提交事物,刷新数据库,将数据写入
            sqlSession.close();//关闭流
            if (i>0){
                System.out.println("成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}

多个参数传递的问题

1@Param (“名称”) 就是在我们sql语句中使用的变量名(推荐)
     #{名称}
2: 使用map集合的传参
    #{key}
3: 使用参数的下标
#{arg0}。。。。。

示例代码
接口
   //@Param(“名称”) 就是在我们sql语句中使用的变量名
int saveByParam(@Param("id") int id, @Param("name") String name,@Param("bir") Date bir, @Param("address") String address);
//使用map集合的传参   key-value     执行单元#{key名称}
int saveByMap(Map<String,Object> map);
//使用参数的下标
int saveByIndex(int id,String name,Date bir,String address);

对应的Mapper

 <!-- 通过参数下标 @Param(“名称”)属性不需要设置 #{名称}  **推荐**-->
 <insert id="saveByParam" parameterType="com.study.mybatis.pojo.Person">
    INSERT INTO `person`(`id`, `name`, `bir`, `address`)
    VALUES (#{id},#{name},#{bir},#{address});
</insert>
<!--  #{key名称}  -->
<insert id="saveByMap" parameterType="java.util.Map">
    INSERT INTO `person`(`id`, `name`, `bir`, `address`)
    VALUES (#{id},#{name},#{bir},#{address});
</insert>

 <!--
    #{arg下标}0开始
    #{param下标}1开始
    -->
<insert id="saveByIndex" parameterType="java.util.Map">
    INSERT INTO `person`(`id`, `name`, `bir`, `address`)
    VALUES (#{param1},#{param2},#{param3},#{param4});
</insert>

测试方法

@Test
public void testSaveByParam(){
    String fileName="mybatis-config.xml";
    try {
        InputStream inputStream = Resources.getResourceAsStream(fileName);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = factory.openSession();//alt+enter
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = format.parse("2019-12-31");
        int result = mapper.saveByParam(0, "jack", parse, "广东");
        sqlSession.commit();
        sqlSession.close();
        System.out.println(result);
    } catch (IOException | ParseException e) {
        e.printStackTrace();
    }
}

@Test
public void testSaveByMap(){
    String fileName="mybatis-config.xml";
    try {
        InputStream inputStream = Resources.getResourceAsStream(fileName);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = factory.openSession();//alt+enter
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = format.parse("2019-12-31");
        Map<String,Object> map=new HashMap<>();
        map.put("id",0);
        map.put("name","xixi");
        map.put("bir",parse);
        map.put("address","广东");

        int result = mapper.saveByMap(map);
        sqlSession.commit();
        sqlSession.close();
        System.out.println(result);
    } catch (IOException | ParseException e) {
        e.printStackTrace();
    }
}

@Test
public void testSaveByIndex(){
    String fileName="mybatis-config.xml";
    try {
        InputStream inputStream = Resources.getResourceAsStream(fileName);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = factory.openSession();//alt+enter
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = format.parse("2019-12-31");
        int result = mapper.saveByIndex(0, "tomer123", parse, "广东");
        sqlSession.commit();
        sqlSession.close();
        System.out.println(result);
    } catch (IOException | ParseException e) {
        e.printStackTrace();
    }
}

主键值:

Mybatis: 标签 selectKey 帮助我们获取数据库管理的主键值
利用一下我们数据库查询主键值的方式
1)  increment  select  last_insert_id()
2)  uuid()    select  uuid(); -- mysql数据库生成一个全球唯一不重复的字符串

示例代码
接口
public int save(Person per);
对应的mapper
 <!-- 返回保存了当前对象的主键值
       keyProperty: 类中的主键字段匹配的属性
       keyColumn: 表中的那个字段是主键字段
       order: BEFORE(先获取主键然后再插入数据)   AFTER(先插入数据,在获取主键)
       resultType: 主键的类型是什么 
    -->
<insert id="save" parameterType="com.study.mybatis.pojo.Person">
    <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int">
        select LAST_INSERT_ID();
    </selectKey>
    INSERT INTO `person`(`id`, `name`, `bir`, `address`)
    VALUES (#{id},#{name},#{bir},#{address});
</insert>
测试类:
public void testSaveInfo() {
		//定义配置文件路径
		String fileName="mybatis-config.xml";
		try {
			//通过配置文件创建输入流对象
			InputStream inputStream = Resources.getResourceAsStream(fileName);
			//读取配置文件 实例化我们工厂
			SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession session = factory.openSession();
			//通过反射机制获取接口对象
			PersonMapper mapper = session.getMapper(PersonMapper.class);
			//创建对象
			Person person=new Person(11,"孙芳",new Date(),"广州市");
			//调用接口方法
			int result = mapper.saveInfo(person);
			//增删改操作需提交事务
			session.commit();
			//关闭
			session.close();
			System.out.println("受影响行数:"+result);
			//获取方式
			System.out.println("插入后 id:"+person.getId());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}




查询操作

接口

//单个对象查询
Person getById(int id);
//查集合
List<Person> list();
//查数值
int count();

mapper.xml

<!-- resultType  指的是返回值类型
   要求:实体中的属性名要与表的中字段名要一致
      确保返回的结果<=1-->
      //查询一个实例时候返回类型,就是实际要返回的类型的全路径包括包装类
<select id="getById" resultType="com.study.mybatis.pojo.Person" parameterType="int">
    SELECT * FROM `person` WHERE `id`=#{id}
</select>
<!--    当返回的是一个对象集合的时候,返回值类型是泛型指定的类型的全路径,包括包装类也是-->
//这么长的全类型名可在全局mybatis里使用别名来简化写法
<select id="list" resultType="com.study.mybatis.pojo.Person" >
    SELECT * FROM `person`
</select>

<select id="count" resultType="int" >
    SELECT COUNT(*) FROM `person`
</select>


测试:

@Test
public void testGetById(){
    //加载全局置文件
    String fileName="mybatis-config.xml";
    try {
        //Resources是mybatis中提供的一个工具类
        InputStream inputStream = Resources.getResourceAsStream(fileName);
        //创建工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂拿到一个会话

            SqlSession sqlSession = factory.openSession();
            //通过反射拿到接口
            PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
            System.out.println("------查单个-------");
            Person person = mapper.getById(2);
            System.out.println(person);
            System.out.println("------查集合-------");
            List<Person> list = mapper.list();
            for (Person person1 : list) {
                System.out.println(person1);
            }
            System.out.println("------查数值-------");
            int count = mapper.count();
            System.out.println("一共有:"+count);


            sqlSession.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Sql片段

针对在mybatis配置文件中重复书写的sql内容,我们可以采用sql片段封装的方式完成,如果在其他的sql中使用,我们只需导入这个公共sql段

Sql段的定义:

<!-- 定义 SQL 片段 --> <!-- 
[sql 标签 ]:定义一个 SQL 片段 [id]:SQL 片段的唯一标识 建议: 
1、SQL 片段中的内容最好是以单表来定义 2、如果是查询字段,则不要写上 SELECT 3、如果是条件语句,则不要写上 WHERE 
 -->
<sql id="select_user_where">
   <if test="userExt != null">
          <if test="userExt.sex != null and userExt.sex != ''">
             AND sex = #{userExt.sex}
          </if>
          <if test="userExt.username != null and userExt.username != ''">
              AND username LIKE '%${userExt.username}%' 
          </if> 
    </if> 
</sql> 



Sql段的使用
Sql中使用标签<include refid=”sql段定义的时候我们声明sql段的id值”>
<!-- 根据用户 id 来查询用户信息(使用 SQL 片段) -->
<!-- 
[include 标签 ]:引用已经定义好的 SQL 片段 
[refid]:引用的 SQL 片段 id 
--> 
<select id="findUserList" parameterType="person"  resultType="person">
  SELECT * FROM person
  <where>
      <include refid="select_user_where"/>
  </where>
</select>



自定义ResultMap(映射) & resultType(默认)

表中是字段和类中是属性不一致,导致我们查询的结果不符合预期类型。
<!--  自定义的映射类型 -->
 <resultMap type="com.study.bean.Person" id="newPerson">
      <!-- 主键字段的配置  -->
      <id property="id" column="id"></id>
      <!--  普通字段的配置 -->
      <result property="names" column="name"></result>
      <result property="bir" column="bir"/>                             
 </resultMap>
resultMap属性
Type: 当前的bean对象类型(数据模型的类型)
Id: 新的类型的标记 标识

resultMap子标签
<id> 标签:主键标签,配置的主键的映射关系 
resultMap: 普通字段的映射关系


typeAliases别名

别名: mapper.xml 中经常使用到bean 模型的配置,声明类型的时候,类的全部名称。多个标签重复写出。别名就是决绝多个标签重复写bean类型
Select …. From Emp_employee_info e,Dept_dept_info d where e.id=d.id;
Mybatis: 声明类的别名,在mybatis-config.xml
< typeAliases>
      < typeAliase type=”类的描述” aliase=”定义名字”  ></ typeAliase>
</ typeAliases>

示例
  <typeAliases>
       <!-- 
          type: bean类型
          alias:(StudentMessage) 类名
        -->
        <typeAlias type="com.study.bean.Person" alias="Person"/>
         <!-- 直接扫描实体类的包 -->
 	 	<package name="beike.mybatis.pojo"/>
  </typeAliases>

Mybatis: 使用类的别名,在***mapper.xml
ParameterType   resultType : 属性中使用别名

JdbcType

在给sql传入参数,指定当前的参数的mybatis类型
#{变量名,jdbcType= 类型}
示例
<insert id="save" parameterType="Person">
    insert into person(id, name,bir)

    values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{ bir,jdbcType=TIMESTAMP})
</insert>

大部分操作中都不会指定这个类型,mybatis会默认给我们指定当前的这个类型,开发中基本上使用的就是mybatis默认给我们的匹配类型。

总结:

Mybatis: orm框架,代替了jdbc数据持久化操作。

为什么使用mybatis放弃jdbc(面试题)
1:jdbc 代码冗余 Statement  ResultSet
2:sql语句和java代码耦合在一起,不利于程序的更新扩展。
3:频繁的打开和关闭连接耗费资源(连接池,自动回收连接,连接重复利用)
4:  事务控制,setAutoCommit(false) commit  rollback setAutoCommit(true),mybatis 直接将事务的处理器进行封装。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值