Mybatis 深入学习笔记

JDBC问题分析:
1、数据库配置存在硬编码 (配置文件解决)
2、频繁创建释放数据库连接 (连接池解决)
3、sql语句、设置参数、获取结果集参数 硬编码 (配置文件解决)
4、手动封装返回结果集,较为繁琐 (反射、内省解决)
自定义持久层框架设计思路:
使用端:(项目)引入自定义持久层框架的jar包
提供两部分配置信息:数据库配置信息、sql配置信息:sql语句、参数类型、返回值类型
使用配置文件提供配置信息:
(1)sqlMapConfig.xml:存放数据库配置信息,存放mapper.xml的全路径
(2)mapper.xml:存放sql配置信息
自定义持久层框架本身:(工程)本质是对JDBC代码进行封装
(1)加载配置文件:根据配置文件路径,加载配置文件成字节输入流,存储在内存中
创建Resources类 方法: InputSteam getResourcesAsSteam(String path)
(2)读取配置文件,创建javaBean:(容器对象):存放对配置文件解析出来的内容
Configuration:核心配置类:存放sqlMapConfig.xml解析出来的内容
MappedStatement:映射配置类:存放mapper.xml解析出来的内容
(3)解析配置文件:dom4j
创建类:SqlSessionFactoryBuilder 方法:build(InputSteam in)
第一:使用dom4j解析配置文件,将解析出来的内容封装到容器对象中
第二:创建SqlSessionFactory对象;生产sqlSession:会话对象(工厂模式)
(4)创建SqlSessionFactory接口及实现类DefaultSqlSessionFactory
第一:openSession() :生产sqlSession
(5)创建SqlSession接口及实现类DefaultSession
定义对数据库的crud操作:selectList()、selectOne()、update()、delete()
(6)创建Executor接口及实现类SimpleExecutor
query(Configuration,MappedStatement,Object… params):执行的就是JDBC代码

优化:
自定义持久层框架中存在如下问题
1.重复加载配置文件、创建SQL SessionFactory、创建sqlSession
2.硬编码访问statementId(maaper.xml中的sql名)
解决:使用代理模式生成Dao接口的代理对象(代理对象实际上是一个proxy,无论调用接口中的任意一个方法,都会调用动态代理类的invoke方法

Mybatis复杂映射:
一对一:实体类中包含另一个类
配置方式:

<mapper namespace="com.lagou.mapper.OrderMapper">
	<resultMap id="orderMap" type="com.lagou.domain.Order">
		<result column="uid" property="user.id"></result>
		<result column="username" property="user.username"></result>
		<result column="password" property="user.password"></result>
		<result column="birthday" property="user.birthday"></result>
	</resultMap>

	<select id="findAll" resultMap="orderMap">
		select * from orders o,user u where o.uid=u.id
	</select>
</mapper>
<resultMap id="orderMap" type="com.lagou.domain.Order">
	<result property="id" column="id"></result>
		<result property="ordertime" column="ordertime"></result>
		<result property="total" column="total"></result>
		<association property="user" javaType="com.lagou.domain.User">
			<result column="uid" property="id"></result>
			<result column="username" property="username"></result>
			<result column="password" property="password"></result>
			<result column="birthday" property="birthday"></result>
		</association>
</resultMap>

一对多:实体类中包含另一个类的列表

<mapper namespace="com.lagou.mapper.UserMapper">
	<resultMap id="userMap" type="com.lagou.domain.User">
		<result column="id" property="id"></result>
		<result column="username" property="username"></result>
		<result column="password" property="password"></result>
		<result column="birthday" property="birthday"></result>
		<collection property="orderList" ofType="com.lagou.domain.Order">
		<result column="oid" property="id"></result>
		<result column="ordertime" property="ordertime"></result>
		<result column="total" property="total"></result>
		</collection>
	</resultMap>
	<select id="findAll" resultMap="userMap">
		select *,o.id oid from user u left join orders o on u.id=o.uid
	</select>
</mapper>

多对多:
两个类互相包含对方的列表属性,拆分为两个一对多,配置方式与一对多相同

MyBatis注解:
@Insert:实现新增 @Update:实现更新 @Delete:实现删除 @Select:实现查询

注解一对一

public interface OrderMapper {
@Select("select * from orders")
@Results({
	@Result(id=true,property = "id",column = "id"),
	@Result(property = "ordertime",column = "ordertime"),
	@Result(property = "total",column = "total"),
	@Result(property = "user",column = "uid",
		javaType = User.class,
		one = @One(select = "com.lagou.mapper.UserMapper.findById"))
})
List<Order> findAll();
}
public interface UserMapper {
	@Select("select * from user where id=#{id}")
	User findById(int id);
}

注解一对多:

public interface UserMapper {
@Select("select * from user")
@Results({
	@Result(id = true,property = "id",column = "id"),
	@Result(property = "username",column = "username"),
	@Result(property = "password",column = "password"),
	@Result(property = "birthday",column = "birthday"),
	@Result(property = "orderList",column = "id",
		javaType = List.class,
		many = @Many(select =
		"com.lagou.mapper.OrderMapper.findByUid"))
})
List<User> findAllUserAndOrder();
}
public interface OrderMapper {
	@Select("select * from orders where uid=#{uid}")
	List<Order> findByUid(int uid);
}

Mybatis缓存:
一级缓存以Map形式存在于SqlSession中,二级缓存以map形式存在于mapper对应的namespace中,开启二级缓存时,先查询二级缓存,再查询一级缓存。
二级缓存开启:
configration:


mapper:

二级缓存整合redis:
1.pom文件

org.mybatis.caches
mybatis-redis
1.0.0-beta2

2.配置文件
Mapper.xml

3.redis.properties
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=
redis.database=0

Mybatis插件:
对执行器Executor、SQL语法构建器StatementHandler、参数处理器ParameterHandler、结果集处理器ResultSetHandler四大核心对象的动态代理,并在invoke中进行增强。

自定义插件:
configration:

<plugins>
	<plugin interceptor="com.lagou.plugin.MySqlPlugin">
		<!--配置参数-->
		<property name="name" value="Bob"/>
	</plugin>
</plugins>
@Intercepts({
        @Signature(type= StatementHandler.class,
                  method = "prepare",
                  args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {

    /*
        拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("对方法进行了增强....");
        return invocation.proceed(); //原方法执行
    }

    /*
       主要为了把当前的拦截器生成代理存到拦截器链中
     */
    @Override
    public Object plugin(Object target) {
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }

    /*
        获取配置文件的参数
     */
    @Override
    public void setProperties(Properties properties) {
        System.out.println("获取到的配置文件的参数是:"+properties);
    }
}

pageHelper分页插件使用:
①导入通用PageHelper坐标

com.github.pagehelper
pagehelper
3.7.5


com.github.jsqlparser
jsqlparser
0.9.1

② 在mybatis核心配置文件中配置PageHelper插件

* <!—指定方言 —>

③ 测试分页代码实现

@Test
public void pageHelperTest(){

    PageHelper.startPage(1,1);
    List<User> users = userMapper.selectUser();
    for (User user : users) {
        System.out.println(user);
    }

    PageInfo<User> pageInfo = new PageInfo<>(users);
    System.out.println("总条数:"+pageInfo.getTotal());
    System.out.println("总页数:"+pageInfo.getPages());
    System.out.println("当前页:"+pageInfo.getPageNum());
    System.out.println("每页显示的条数:"+pageInfo.getPageSize());
    }

Builder构建者模式
Builder模式的定义是"将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表
示。”,它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范
围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加
复杂的对象的构建,甚至只会构建产品的一个部分,直白来说,就是使用多个简单的对象一步一步构建
成一个复杂的对象
例子:使用构建者设计模式来生产computer
主要步骤:
1、将需要构建的目标类分成多个部件(电脑可以分为主机、显示器、键盘、音箱等部件);
2、 创建构建类;
3、 依次创建部件;
4、 将部件组装成目标对象

工厂模式
在Mybatis中比如SqlSessionFactory使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂
模式。
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于创
建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建
其他类的实例,被创建的实例通常都具有共同的父类

代理模式
代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式
的英文叫做Proxy,它是一种对象结构型模式,代理模式分为静态代理和动态代理,我们来介绍动态代

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值