mybatis笔记 持续更新

mybatis

为什么要引入mybatis,回答这个问题之前不妨先来看看JDBC的缺点:
硬编码 :SQL语句存在Java代码中,不能很好的分离数据库语句和Java语句,造成代码不易维护;
SQL参数固定:SQL语句的参数固定,使得SQL语句不灵活,无法满足多变的场景。
代码重复度高 :大量的重复代码,以 ResultSet为例,每次都需要重复解析结果集;
底层技术 :JDBC属于底层的技术,不支持分布式,缓存等技术,对于复杂场景的应对不好;

ORM 模型:

ORM 模型是数据库的表和简单 Java 对象(Plain Ordinary Java Object,简称 POJO)的映射关系模型,主

要解决数据库数据和 POJO 对象的相互映射。POJO 对象(Plain Ordinary Java Object):简单的 Java 对象,实际就是普通 JavaBeans。
在这里插入图片描述

映射配置:配置分为:类与数据库中表的映射;对象与表中记录的映射;类的属性与数据库中表的字段的映射。

常见的ORM模型:

HIBERNATE:一个全自动的ORM模型,Hibernate可以自动生成SQL语句,自动执行。

  1. Hibernate是全自动化ORM; Mybatis是半自动化ORM。

  2. Hibernate简化dao层,不用考虑SQL语句的编写和结果映射,重点放在业务逻辑上;
    Mybatis需要手写SQL语句以及结果映射。

  3. Hibernate是一个重量级的框架,内部生成SQL语句,反射操作太多,导致性能下降;

Mybatis是一个轻量级的框架,需要自己写sql语句,有较少的反射操作。

  1. Hibernate 不方便做SQL优化,遇到较复杂的SQL语句需要绕过框架实现复杂,

对多字段的结构进行部分映射困难;

Mybatis 不仅可以做SQL优化还可以SQL与Java分离,还可以自行编写映射关系,

复杂的SQL语句Mybatis效率更高

Mybatis优势:

  • 可以进行更细致的SQL优化;容易掌握

Hibernate优势;

  • dao层开发比mybatis简单,mybatis需要维护SQL和结果映射
  • hibernate数据库移植性好mybatis 解决tis和hibernate 区别:
mybatis 解决了jdbc 的问题:

1.数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。

2.Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3.向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4.对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象

解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

为什么选择MyBatis:

简单易学 :易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现;

灵活度高 :通过定制 SQL 语句,可以比较灵活的访问数据库,获取数据;

功能完整 :提供了连接管理,缓存支持,线程支持,(分布式)事务管理等功能,还提供了其他 ORM 模型的支持。
在这里插入图片描述

项目结构及环境创建:

在这里插入图片描述

其中lib为要用到的包;具体导包请参考:导包教程

bean:用来存放实体类JavaBean

dao:层作用具体参考:点击跳转

mapper:用来存放sqlMapper.xml文件。

jdbc.properties:存放数据库的驱动密码用户名等。

mybatis-config.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>
<!--给单个起别名-->
		<typeAlias type="com.li.Student" alias="a"/>
<!--批量起别名,扫描整个包-->
		<package name="com.li.bean"/>	
	</typeAliases>
	<!-- 和spring整合后 environments配置将废除 -->
	<enviroments default="development">
	<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver" />
				<property name="url"
					value="jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</enviroments>
   
	<mappers>
<!--文件路径sqlMapper文件-->
		<mapper resource="com/li/mapper/StudentMapper.xml"/>
	</mappers>
</configuration>
  • 配置文件层级目录

    1. :标识配置文件的起始,所有配置信息都

    存放在这里

    1. :配置数据库环境信息,注册数据源,配置

    数据库事务

    1. :用来在MyBatis初始化的时候引入映射器
configuration元素:

标识配置文件的起始,所有配置信息都存放在这里

<configuration>
   写配置信息,层次顺序不能变!!!
</configuration>
enviroments元素:

配置数据库环境信息,注册数据源,配置数据库事务。

<enviroments default="development">
	<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver" />
				<property name="url"
					value="jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
</enviroments>

default=“development”:默认使用的数据库环境
id=“development”:单个数据库环境信息的标识
transactionManager type=“JDBC” :配置数据库事务

​ 数据库事务:

  • JDBC:使用 JDBC 的事务管理机制,就是利用 java.sql.Connection 对象完成对事务的交;

  • MANAGED:使用 MANAGED 的事务管理机制,这种机制 MyBatis 自身不会去实现事务管理,而是让程序的容器(JBOSS,WebLogic)来实现对事务的管理;

  • 自定义:由使用者自定义数据库事务的管理方式,适用于特殊应用。dataSource type=“POOLED”:配置环境信息中数据源连接的信息。

dataSource type=“POOLED”:配置环境信息中数据源连接的信息。

  • UNPOOLED:非连接池的数据源
  • POOLED:连接池的数据源
  • JNDI:JNDI的数据源
  • 自定义数据源:其他类型数据源

property :配置环境信息的属性;

思考一个问题:上述写法中的数据库地址,账号密码都是明文的,完全没有安全性可言,这个问题如何解决呢?

​ 答:在外部创建一个jdbc.properties文件内容如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT
jdbc.username=root
jdbc.password=123456

然后在主配置文件中读取该文件(注意读取文件必须在第一个)、再将value中的值改为#{文件名.元素}:

这样做,在开发中无序知道数据库的信息,只需在最后上线发布时将真正的jdbc.properties替换原来的文件就行。

<?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>
	<properties resource="jdbc.properties"></properties>
<!--起别名-->
	<typeAliases>
<!--给单个起别名-->
		<typeAlias type="com.li.Student" alias="a"/>
<!--批量起别名,扫描整个包-->
		<package name="com.li.bean"/>	
	</typeAliases>
	<!-- 和spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<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>
    
	<mappers>
<!--文件路径sqlMapper文件-->
		<mapper resource="com/li/mapper/StudentMapper.xml"/>
	</mappers>
</configuration>
properties元素:

在这里插入图片描述

使用时的建议:①不要使用混合方式,以避免管理混乱 。②首选的方式是 Properties 文件方式。③如存在加密或者安全访问的问题,使用第二种方式,为日后统一管理提供方便

typeAliases元素:

Mybatis内部支持的别名

<!--	起别名-->
	<typeAliases>
<!--给单个起别名-->
		<typeAlias type="com.li.Student" alias="a"/>
<!--批量起别名,扫描整个包-->
		<package name="com.li.bean"/>
	</typeAliases>

起别名之前在sqlMapper中使用时代码如下:

<select id="select" resultType="com.li.Student">
        select * from student
    </select>

使用别名后,下列是使用批量起别名的方法,直接扫描整个包:

<select id="selectAll" resultType="Student">
        select * from student
    </select>

mappers

用来在MyBatis初始化的时候引入映射器。这个也可以先使用批量起别名的方式然后再使用别名扫描

<mappers>
		<mapper resource="com/li/mapper/StudentMapper.xml"/>
</mappers>

在这里插入图片描述

sqlMapper.xml:文件
<!-- 头文件 -->
<?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">

<!-- sql语句 -->
<mapper namespace="test1">
     <!--全查-->
    <select id="selectStuAll" resultType="Student">
        select * from student
    </select>

    <!--按照Sid查询-->
    <select id="selectStuBySid" resultType="Student" parameterType="int">
        select * from student where sid = #{sid}
    </select>

    <!--插入字段-->
    <insert id="insertStu" parameterType="Student">
        insert into student(sname,birthday,ssex,classid) values(#{sname},#{birthday},#{ssex},#{classid})
    </insert>

    <!--删除字段-->
    <delete id="deleteStu" parameterType="int">
        delete from student where sid = #{sid}
    </delete>

    <!--修改字段-->
    <update id="updateStu" parameterType="Student">
        update student set sname=#{sname},birthday=#{birthday},ssex=#{ssex},classid=#{classid}
	 	where sid = #{sid}
    </update>

</mapper>
MyBatis的生命周期:

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

  1. 读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。

  2. 加载映射文件。映射文件即SQL映射文件,该文件中配置了操作 数据库的SQL语句,需要在MyBatis配置文件mybatisconfig.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。

  3. 构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。

  4. 创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。

  5. Executor****执行器:MyBatis底层定义了一个Executor 接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

  6. MappedStatement 对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。

  7. 输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。

  8. 输出结果映射:输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。

动态代理:

什么是动态代理:

在接口中有方法的返回值定义,参数的定义,方法名,在sqlMapper.xml 中也对应这接口给予了赋值,这时候dao的实现类就显得多余,这是Mybatis可以帮助我们自动产生实现类,并可以调取方法得到结果,这就是Mybatis的mapper动态代理。

动态代理的规范:

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper接口开发需要遵循以下规范:

  1. Mapper.xml文件中的namespace与mapper接口的类路径相同。

  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

selectOne和selectList :

动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

namespace

mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

select元素:

<select id="findStudentCount" resultType="int">
        查询语句
</select>

id:唯一标识,接口中的方法名

parameterType:参数类型

resultType:结果的类型

resultMap:复杂的结果集映射关系

符号小于小于等于大于大于等于单引号双引号
原符号<<=>>=&"
替换符号&lt;&lt;=&gt;&gt;=&amp;&apos;&quot;

映射器:

在这里插入图片描述

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

查询中传递多个参数:
<!--通过javabean创建实体对象-->
<select id="findStudentByClassidAndSex" resultType="Student">
        select * from studnt where sid = #{value} and ssex = #{value}
    </select>
<!--通过map进行传递-->
    <select id="findStudentPage" parameterType="map" resultType="Student">
        select * from student limit #{weizhi},#{size}
    </select>

<!--参数必须这样写:param1 param2 param3-->
    <select id="findStudentBySexPage" resultType="Studnet">
        select  * from student where ssex = #{param1} limit #{param2} ,#{param3}
    </select>

<!--参数必须这样写:arg0 arg1 arg2-->
    <select id="findStudentBySexPages" resultType="Student">
        select * from student where ssex = #{arg0} limit #{arg1} ,#{arg2}
    </select>

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

insert元素:

作用是将主键直接进行回填,查询出来的结果中Sid为表中的真实值,没有回填的话,查出来就是0

<!--插入字段:主键回填keyProperty;主键的字段;useGeneratedKeys:是否主键回填,默认是false-->
    <insert id="insertStu" parameterType="Student" keyProperty="sid" useGeneratedKeys="true">
        insert into student(sname,birthday,ssex,classid) values(#{sname},#{birthday},#{ssex},#{classid})
    </insert>

id:唯一标识,接口中的方法名

parameterType:参数类型

keyProperty:表示以哪个列作为属性的主键,不能和 keyColumn 同时使用;

keyColumn:指明哪一列是主键,不能和 keyProperty 同时使用;

useGeneratedKeys:使用 JDBC 的 getGeneratedKeys 方式来取有数据库内部生成的主键;

update元素和delete元素:

 <update id="updateStu" parameterType="Student">
        update student set sname=#{sname},birthday=#{birthday},ssex=#{ssex},classid=#{classid}
	 	where sid = #{sid}
    </update>
 <delete id="deleteStu" parameterType="int">
        delete from student where sid = #{sid}
</delete>

id:唯一标识,接口中的方法名

parameterType:参数类型

resultMap元素:

主角要解决问题:数据库字段与实体类属性不一致问题:
方案一:字段别名,保持跟属性一致
方案二:resultMap

​ 单表可以只写映射不上的
​ 对于主键字段来说可以使用id 也可以使用 result

    <resultMap id="resMap" type="SMaster">
        <id column="smid" property="smid"/>
        <result column="sm_name" property="smname"/>
        <result column="smsex" property="smsex"/>
    </resultMap>

    <select id="findAllSm" resultMap="resMap">
        select * from schoolmaster;
    </select>

    <insert id="insertSMaster" parameterType="SMaster">
        insert into schoolmaster(sm_name,smsex) values (#{smname},#{smsex});
    </insert>

    <insert id="insertSMaster" parameterType="SMaster">
        insert into schoolmaster(sm_name smname,smsex) values (#{smname},#{smsex});
    </insert>

reeultMap中的属性说明:

property:映射到列结果的字段或者属性,通常是指 POJO 的属性;

column:对应的数据库字段;

javaType:Java 类型,可以是基本数据类型,也可以是类完全限定名;

jdbcType:JDBC 的类型,基本支持所有常用的数据库类型;

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

多表联查:

级联:级联(cascade),是指多个对象之间的映射关系,建立数据之间的级联关系提高管理效率。

  • 一对一:一个对应唯一的身份对象;eg:中国公民和身份证
  • 一对多:一个对象对应多个对象;eg:班级和学生
  • 多对多:多个对象对应多个对象;eg:公司角色和公司员工
一对一:

在这里插入图片描述

首先在实体类中添加级联表的对象:

在这里插入图片描述
在Student中添加association属性(多表联查中没有显示映射的字段不会赋值):
在这里插入图片描述

一对多:

首先在实体类中添加级联表的对象list集合:

在这里插入图片描述

sqlMapper.xml:

ofType:使用该属性指定集合中的元素的。
在这里插入图片描述

Mybatis中不允许方法重载,因为sqlMapper文件中的id是唯一标识,不能重复

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值