MyBatis框架

参考网站
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.OracleDriver
url = jdbc:oracle:thin:@localhost:1521:xe
username = hr
password = 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测试

@Test
public 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注解进行参数绑定[建议]

注:

 <![CDATA[]]>

mybaits中消除xml大小写

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>

案例
serviceimpl层

public User regist(User user) {
        SqlSession session = MyBatisUtil.openSqlSession();
        UserDAO ud = (UserDAO) session.getMapper(UserDAO.class);
        User u = null;
        try {
            ud.insertSelective(user);
            u = ud.selectByEmail(user.getdEmail());
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.close();
        }

        return u;
    }

注意从session获取Mapper执行后注意commit

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

idusenameagesalarydid
1hibiscidai18100001
1laowang181001

t_department

idepartmentnameepartmentnumber
1研发部1111

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

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

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

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

t_student | 学生表

idstudentnumberstudentnameage
11111hibiscidai18
12222hibiscizhang28
13333hibisciwang38

t_sc | 多对多映射表

idsidcid
111
211
321
422

t_course | 课程表

idcoursenamescore
1java3
2oracle2

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值