MyBatis框架

来源:互联网 发布:java中offset什么意思 编辑:程序博客网 时间:2024/06/08 09:27

    • MyBatis框架
  • MyBatis框架引言
    • 1-1 MyBatis框架的基本概念
    • 1-2 MyBatis框架与JDBC对比
    • 1-3 MyBatis框架的核心编程思路
  • 第一个MyBatis程序的开发HelloWorld
    • 2-1 环境搭建OpenSource
      • 2-1-1 导入jar包
      • 2-1-2 引入配置文件
        • 2-1-2-1 log4jproperties可选
        • 2-1-2-2 MyBatis-configxml
        • 2-1-2-3 Mapper文件
      • 2-1-3 初始化配置
        • 2-1-3-1 补充MyBatis-config中的配置信息
    • 2-2 MyBatis API
      • 2-2-1 Resources
      • 2-2-2 SqlSessionFactory
      • 2-2-3 SqlSession
    • 2-3 MyBatis 的开发步骤
  • 参数绑定
    • 3-1 Mybaits代码中形参名与mapper文件中的的名字没有必然联系
    • 3-2 Mapper文件中可以通过下标的形式代表接口中的形参
    • 3-3 多参数形式的查询解决方案
      • 3-3-1 可以通过下标的形式进行操作
      • 3-3-2Param注解进行参数绑定建议
      • 3-3-3 使用集合map进行传参早期
  • MyBatis中CUD增删改
    • 4-1 删除
    • 4-2 修改
    • 4-3 插入
  • MyBatisUtil工具类的封装
  • ResultMap结果映射结果对应关系
    • 6-1 定义ResultMap
    • 6-2 使用ResultMap
  • MyBatis框架进行多表操作
    • 7-1 实体之间的关系分类
    • 7-2 MyBatis中如何处理管理关系
      • 7-2-1 entity处理
      • 7-2-2 表
      • 7-2-3 DAO接口
      • 7-2-4 Mapper文件处理
  • 关联关系的实战开发
    • 8-1 11关联关系
    • 8-2 1关联关系重点
    • 8-3 关联关系了解
    • 8-4 关联关系总结
      • 8-4-1 Entity 关系属性
      • 8-4-2 Table外键
      • 8-4-3 Mapper文件
  • 动态SQL
    • 9-1 Sql片段
    • 9-2 where语句的动态Sql
    • 9-3 修改操作的动态Sql
    • 9-4 批量操作批量删除批量查询
  • MyBatis的缓存Cache
    • 10-1 缓存简述
    • 10-2 缓存开启步骤
      • 10-2-1 开启MyBatis的全局缓存
      • 10-2-2 设置需要存储在缓存中的数据
      • 10-2-3 放置在缓存中的实体对象都需要实现serializable接口

参考网站
mybatis中文文档
mybatis源码中文注释

**

MyBatis框架

**

1 MyBatis框架引言

1-1 MyBatis框架的基本概念

MyBatis是一个持久层框架,完成对数据库的访问(CRUD)

1-2 MyBatis框架与JDBC对比

jdbc访问和操作数据库存在的问题:
i.大量的代码冗余
ii.手工处理ORM(麻烦)
iii.没有对数据库进行优化(Cache)
解决JDBC访问和操作数据库存在 的问题,是对原有JDBC技术的封装。

1-3 MyBatis框架的核心编程思路

MyBatis的核心开发思路.png
在原来的JDBC三层模型汇总,先进行书写DAO接口后实现DAO实现类,MyBatis的解决思路是使用mapper xml类型文件代替DAO实现类的功能。

2 第一个MyBatis程序的开发(HelloWorld)

2-1 环境搭建(OpenSource)

i.Ibatis是MyBatis的前身,apache组织
ii.IBatis从3.0开始改名为MyBatis google code
iii.MyBatis 属于GitHub

2-1-1 导入jar包

  • MyBatis的核心jar包
  • 第三方依赖jar
  • 相关数据库的驱动jar

2-1-2 引入配置文件

2-1-2-1 log4j.properties[可选]

log4日志文件放置在src目录下

2-1-2-2 MyBatis-config.xml

建议放置在src目录下
配置的是MyBatis运行的相关参数

2-1-2-3 Mapper文件

实现DAO接口
位置建议xxxDao接口放在同一目录下

2-1-3 初始化配置

MyBatis-config.xml配置

oracle数据库配置

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" ><configuration>    <environments default="oracle">        <environment id="oracle">            <transactionManager type="JDBC"></transactionManager>            <dataSource type="POOLED">                <property name="driver" value="oracle.jdbc.OracleDriver" />                <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />                <property name="username" value="hr" />                <property name="password" value="hr" />            </dataSource>        </environment>    </environments>    <mappers>        <mapper resource="com/baizhi/dao/UserMapper.xml" />    </mappers></configuration>

< environments default=”oracle”>默认环境
< environment id=”oracle”>环境的唯一标识
< transactionManager type=”JDBC”>采用JDBC的事务控制
< dataSource type=”POOLED”>MyBatis原生的连接池
< mapper resource=”com/baizhi/dao/UserMapper.xml” />注册Mapper文件

2-1-3-1 补充MyBatis-config中的配置信息

别名TypeAlias

实体的权限定名

<typeAlias>    <typeAlias type="com.hibiscidai.entity.User" alias="A" /></typeAlias>
<select id="selectByNameAndPassword" resultType="A">    select * from t_user where username=#{username} and password=#{passowrd}</select>

配置内容参数化
问题:在mybatis-config文件中有经常需要修改的字符串相关(数据库相关)
解决方案:把在mybatis-config配置文件中经常需要修改的字符串信息提取到小配置文件中

i.读取小配置文件

<!-- 读取小配置文件 --><properties resource="jdbc.properties"></properties>

resource=”jdbc.properties”——小配置文件存放路径

ii.${key}获取小配置文件中对应的值

<dataSource type="POOLED">    <property name="driver" value="${driver}"/>    <property name="url" value="${url}"/>    <property name="username" value="${username}"/    <property name="password" value="${password}"/></dataSource>  
driver = oracle.jdbc.OracleDriverurl = jdbc:oracle:thin:@localhost:1521:xeusername = hrpassword = hr

2-2 MyBatis API

三个重要的类

2-2-1 Resources

读取mybaitis-fonfig配置文件,打开IO

2-2-2 SqlSessionFactory

通过SqlSessionFactory这个工厂创建SqlSession对象

2-2-3 SqlSession

作用:

i.根据程序员书写的Mapper文件,自动创建mapper文件对应的java类(DAO接口的实现类)
ii.SqlSession内部封装了Connection对象
iii.SqlSession控制事务
SqlSession.commit——Connection.commit
SqlSession.rollback——Connection.rollback

注意:实战开发中,增删改需要控制事务 查询不需要控制事务

2-3 MyBatis 的开发步骤

i.建表
ii.写实体
iii.DAO接口
iiii.Mapper文件做DAO的实现

public User selectByID(Integer id);
<select id="selectByID" parameterType="int" resultType="com.hibiscidai.entity.User">    select * from t_user where id=#{id}</select>

UserresultType=”com.hibiscidai.entity.User”
selectByIDid=”selectByID”
Integer idparameterType=”int”

v.Mapper文件的注册

<mappers>    <mapper resource = "com/hibiscidai/dao/UserMapper.xml" /></mappers>

vi.MyBatis核心API测试

@Testpublic void testMybatis() throws Exception {    // 读取mybatis-config配置文件    InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");    // 创建SqlSessionFactory对象    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);    // 创建SqlSession对象    SqlSession sqlSession = sqlSessionFactory.openSession();    // 创建DAO的实现类    UserDAO userDAO = sqlSession.getMapper(UserDAO.class);    // 调用DAO中相关方法    User user = userDAO.selectByID(1);    System.out.println(user);}

3 参数绑定

3-1 Mybaits代码中形参名与mapper文件中的#{}的名字没有必然联系

public User selectByID(Integer id);
<select id="selectByID" parameterType="int" resultType="com.hibiscidai.entity.User">    select * from t_user where id=#{hibiscidai}</select>

Integer idhibiscidai

3-2 Mapper文件中可以通过下标的形式,代表接口中的形参

public User selectByID(Integer id);
<select id="selectByID" parameterType="int" resultType="com.hibiscidai.entity.User">    select * from t_user where id=#{0}</select>

Integer id0

下标默认从0开始

3-3 多参数形式的查询解决方案

注意:在mybatis进行查询时,paramterType是可以省略的,不能随意指定#{},名字

3-3-1 可以通过下标的形式进行操作

public User selectByNameAndPassword(String username, String password);
<select id="selectByNameAndPassword" resultTpe="com.baizhi.entity.User">    select * from t_user where username=#{0} and password=#{1}</select>

3-3-2@Param注解进行参数绑定[建议]

public User selectByNameAndPassword(@Param("u")String username, @Param("p") String password);
<select id="selectByNameAndPassword" resultType="com.hibiscidai.entuty.User">    select * from t_user where username=#{u} and password=#{p}</select>

3-3-3 使用集合(map)进行传参[早期]

Map<String, String> map = new HashMap<String, String>();map.put("username", "hibiscidai");map.put("passowrd", "123456");User user = userDAO.selectByNameAndPassword(map);
select * from t_user where username=#{username} and password=#{passowrd}
public User selectByNameAndPassword(Map<String, String> params);

4 MyBatis中CUD(增删改)

注意:在MyBatis应用的过程中,处理CUD时,必须要手工控制事务,否则操作不执行

sqlSession.commit();sqlSession.rollback();

4-1 删除

public void delete(Integer id);
<delete id="delete">    delete from t_user where id=#{id}</delete>

4-2 修改

public void update(User user);
User {    id    username    password}
<update id="update">    update t_user set username=#{username}, password=#{password} where id=#{id}</update>

4-3 插入

Sequence序列进行主键插入[Oracle]

public void insert(User user);
User {    id = null    username = hibiscidai    passowrd = 123456}
<insert id="insert">    <selectKey keyProperty="id" order="BEFORE" resultType="int">        select z.newxval from dual    </selectKey>    inset int t_user (id, username, password) values(#{id}, #{usename}, #{password})</insert>

5 MyBatisUtil工具类的封装

对于MyBatis三种类对象的分析
Resources类
特点:读取MyBatis-config配置文件 IO
建议:一次性通过IO读取所有的数据
SqlSessionFactory类
特点:创建SqlSession 重量级的资源 内存占用多 功能多
建议:每一个应用只创建一个 线程安全
SqlSession类
特点:清零及资源 不能被多线程共享
1.创建DAO接口的实现类(动态代理设计思想 动态字节码技术)
2.SqlSession内部封装Connnection 一个SqlSession对应一个Connection
3.事务控制
SqlSession.commit
SqlSession.rollback

import java.io.IOException;import java.io.InputStream;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class mybatisutils {    public static SqlSessionFactory sqlSessionFactory;    public static ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();    /* 静态代码块加载基础信息 */    static {        InputStream stream = null;        try {            // 读取mybatis-config配置文件            stream = Resources.getResourceAsStream("mybatis-config.xml");            // 创建SqlSessionFactory对象            sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);        } catch (IOException e) {            // TODO: handle exception            e.printStackTrace();            throw new RuntimeException("读取配置文件失败");        } finally { // 关闭流            try {                stream.close();            } catch (Exception e2) {                // TODO: handle exception                e2.printStackTrace();            }        }    }    /* 获取SqlSession对象 */    public static SqlSession opSqlSession() {        SqlSession sqlSession = tl.get();        // 非空判断        if (null == sqlSession) {            sqlSession = sqlSessionFactory.openSession();            tl.set(sqlSession);        }        return sqlSession;    }    /* 关闭SqlSession对象 */    public static void closeSqlSession() {        // 获取SqlSession        SqlSession sqlSession = opSqlSession();        sqlSession.close();        tl.remove();    }    /* 事务提交 */    public static void commit() {        SqlSession sqlSession = opSqlSession();        sqlSession.commit();        closeSqlSession();    }    /* 事务回滚 */    public static void rollback() {        SqlSession sqlSession = opSqlSession();        sqlSession.rollback();        closeSqlSession();    }    /* 获取DAO实现 */    public static Object getMapper(Class clazz) {        SqlSession sqlSession = opSqlSession();        return sqlSession.getMapper(clazz);    }}

6 ResultMap(结果映射,结果对应关系)

作用:解决了实体类与数据库中的表不匹配

6-1 定义ResultMap

<resultMap type="Customer" id="CustomerResultMap">    <id property="id" column="t_id" />    <result property="username" column="t_username" />    <result property="password" column="t_password" /></resultMap>

< id >标签表示对主键的处理
< result >标签表示对费主键的处理

property – 代表实体的名字
column – 代表数据库中的列名

6-2 使用ResultMap

<resultMap type="Customer" id="CustomerResultMap">    <id property="id" column="t_id" />    <result property="username" column="t_username" />    <result property="password" column="t_password" /></resultMap><select id="selectByID" resultType="CustomerResultMap" >    select * from t_customer where t_id=#{id}</select>

注意:如果在开发中,只解决列名不一致的问题,有简化的方式,起别名

<typeAliases>    <typeAlias type="com.baizhi.entity.Customer" alias="Customer"/></typeAliases><select id="selectByID" resultType="Customer" >        select  t_id  as id,t_username  as username,t_password as password from t_customer where t_id=#{id}</select>

7 MyBatis框架进行多表操作

7-1 实体之间的关系分类

i.实体之间有关联关系(有 从属 has a)【重点】
a) 1 : 1
b) 1 : *
c) * : *
ii.实体之间继承关系(is a)

7-2 MyBatis中如何处理管理关系

7-2-1 entity处理

关系属性:把关系另一方作为本方属性进行存储

关系的方向性:
单向关系:只能从关系其中一方 找到关系的另一方
双向关系:从关系的双方都可以找到关系的另一方

级联查询:
PersonDAO.query(id) —> Person(passport)
PassportDAO.query(id) —> Passport(person)
看似是单表处理 实际完成多张表的操作

7-2-2 表

表中如何简历关联关系:外键

建外键规则:
一对一 随便建
一对多 建在多的一方
多对多 建在第三张表中

表中关系的方向行:天生的双向关系

注意
1.父没有外键 先插入
2.子表没有外键 先删除

7-2-3 DAO接口

有几个DAO, 对应写几个DAO

7-2-4 Mapper文件处理

自定义结果映射

8 关联关系的实战开发

8-1 1:1关联关系

<resultMap type="Person" id="PersonResultMap">         <id  column="pid" property="id"/>         <result column="pusername" property="username"/>         <result column="page"  property="age"/>         <association property="passport"  javaType="Passport">             <id  column="sid" property="id"/>             <result column="sserial" property="serial"/>             <result column="splace" property="place"/>         </association>     </resultMap>

8-2 1:*关联关系(重点)

例:
部门(Department)与职员(Employee)关系

Employee    id    username    age    salary    department
Department    id    departmentname    departmentnumber    List<Employee> employees

t_employee

id usename age salary did 1 hibiscidai 18 10000 1 1 laowang 18 100 1

t_department

id epartmentname epartmentnumber 1 研发部 1111

一对多关联关系,集合作为关系属性,需要对集合进行初始化操作。

8-3 * : *关联关系(了解)

例:
学生(Student)与课程(Course)关系

Student    id    studentnumber    studentname    age    List<Course>
Course    id    coursename    score    List<Student>

t_student | 学生表

id studentnumber studentname age 1 1111 hibiscidai 18 1 2222 hibiscizhang 28 1 3333 hibisciwang 38

t_sc | 多对多映射表

id sid cid 1 1 1 2 1 1 3 2 1 4 2 2

t_course | 课程表

id coursename score 1 java 3 2 oracle 2

8-4 关联关系总结

8-4-1 Entity 关系属性

a)一个对象b)集合 进行初始化

8-4-2 Table外键

一对一 随便建一对多 建在多的一方多对多 建在第三张表中

8-4-3 Mapper文件

ResultMap
一个对象

<association property="" javaType="">

多个对象

<collection property="" oftype="">

9 动态SQL

作用:简化mapper文件的配置

9-1 Sql片段

<sql id="selectAll">    select * from t_teacher</sql><select id="selectByID" resutlType="Teacher">    <include refid="selectAll" />where id=#{id}</select><select id="selectByName" resultType="Teacher">    <include refid="selectAll" />where teachername=#{name}</select>

9-2 where语句的动态Sql

作用:同样的表,根据不同列的内容查询,通过where的动态sql

TeacherDAO文件重构
未使用where

//根据教师的ID查询该教师public Teacher selectByID(Integer id);//根据教师的姓名查询该教师public Teacher selectByName(String name);//根据教师的序列号查询public Teacher selectByNumber(String number);//根据教师的id及姓名查询public Teacher selectByIDAndName(@Param("id")Integer ID,@Param("name")String name);

使用where后

public Teacher selectByWhere(Integer id, String name, String number)

Mapper文件重构
未使用where

<sql id="selectAll">    select * from t_teacher</sql><select id="selectByID" resutlType="Teacher">    <include refid="selectAll" />where id=#{id}</select><select id="selectByName" resultType="Teacher">    <include refid="selectAll" />where teachername=#{name}</select><select id="selectByNumber" resultType="Teacher">    <include refid="selectAll" />where teachernumber=#{number}</select><select id="selectByIDAndName" resultType="Teacher">    <include refid="selectAll" />where id=#{id} and teachername=#{name}</select>

使用where后

<sql id="selectAll">    select * from t_teacher</sql><select id="selectByWhere" resultType="Teacher">    <include refid="selectAll" />    <where>        <if test="id!=null">            id=#{id}        </if>        <if test="name!=null">            and name=#{name}        </if>        <if test="number!=null">            and number=#{number}        </if>        select * from t_teacher where id=#{id}        select * from t_teacher where name=#{name}        select * from t_teacher where number=#{number}        select * from t_teacher where id=#{id} and name=#{name}    </where></select>

xml逻辑映射:

name=null, number=null  where id=#{id}id=null, number=null        where name=#{name}id=null, name=null      where number=#{number}number=null     where id=#{id} and number=#{number}
<select id="selectByDynamic" resultType="Teacher">    <include refid="selectAll" />    <where>        <if test="id!=null">            id=#{id}        </if>        <if test="teachername!=null">            and teachername=#{teachername}        </if>        <if test="teachernumber!=null">            and teachernumber=#{teahcernumber}        </if>    </where>

注意:用where动态sql时候,多参数做参数绑定时,要与数据库中的列名保持一致。
如果起始条件为null则忽略and号

新的写法:

<trim prefix="where" prefixOverrides="and/or">    <if test="id!=null">        id=#{id}    </if>    <if test="teachername!=null">        and teachername=#{teachername}    </if>    <if test="teachernumber!=null">        and teachernumber=#{teachernumber}    </if></trim>

prefix 忽略前缀
prefixOverrides 忽略前缀and或者or

9-3 修改操作的动态Sql

<update id="updateTeacher">    update t_teacher    <set>        <if test="teachername!=null">            teachername=#{teachername},                 </if>        <if test="teachernumber!=null">            teachernumber=#{teachernumber},        </if>        <if test="age!=null">            age=#{age}        </if>    </set>    where id=#{id}</update>

新的写法

<trim prefix="set" suffixOverrides=",">    <if test="teachername!=null">        teachername=#{teachername},    </if>    <if test="teachernumber!=null">        teachernumber#={teachernumber},    </if>    <if test="age!=null">        age=#{age}    </if></trim>where id=#{id}

9-4 批量操作(批量删除,批量查询)

<select id="selectByIDs" resyltType="Teacher">    select * from t_teacher where id in    <foreach collection="array" open="(" items="ids" separator="," close=")">        #{ids}    </froeach></select>
select * from t_teacher where id in<foreach collection="list" open="(" item="ids" separator=","close=")"></foreach>

如果参数是list集合 collection属性值设置为list

10 MyBatis的缓存(Cache)

10-1 缓存简述

作用:
在应用程序与数据库之间建立内存缓冲,存储用户曾经查询过的数据
好处:
1.减少与数据库之间的频繁通信
2.内存中随机读写效率高于硬盘
问题:
1.内存造价高,内存物理上线不大 无法缓存海量数据
2.数据安全性差
原则:
缓存中存储的数据一定是经常需要查询的数据,而且不是经常需要修改的数据

10-2 缓存开启步骤

10-2-1 开启MyBatis的全局缓存

Mybatis-config.xml配置

<!-- 激活全局缓存 --><settings>    <setting name="cacheEnabled" value="true" /></setting>

10-2-2 设置需要存储在缓存中的数据

<!-- cache标签的作用:本mapper文件中的所有有关查询的操作都会放入mybatis的缓存中 --><cache></cache><select id="selectByID" resultType="Person">    select * from t_person where id=#{id}</select>

注意实体类起别名

10-2-3 放置在缓存中的实体对象都需要实现serializable接口

public class Person implements Serializable {    private Integer id;    private String username;    private String password;    private Integer age;    public Integer getId() {}    ...}

序列化目的:唤出策略(用少的数据写入硬盘中)
注意:
只有session关闭时,MyBatis才会把数据存储在缓存中
事务提交时(CUD),MyBatis会自动清空缓存
建议:
查询方法不需要控制,但是一定要关闭SQLsession
CUD必须要控制事务
单表查询建议采用MyBatis缓存
第三方缓存:
eacache,redis,memcache

原创粉丝点击