Mybatis初步总结

Mybatis 总结

一些总结:

Mybatis操作的是持久层,Mybatis和hibernate一样也有orm(object relational mapping)对象关系映射
Mybatis的主要对象:sqlsessionfactory、sqlsession、executor
四大核心对象:StatementHandler(负责sql语句)、PrameterHandler(负责sql中的参数)、executor
(负责sql执行)、ResultSetHandler(负责结果集)
四大处理器:StatementHandler、PrameterHandler、ResultSetHandler、TypeHandler

一些约定:

1.mapper里面的标签的parameterType和resultType只能各有一个
2.增加对象的时候可以写对象,当parameterType的类型是简单类型(8大基本数据类型+String)
则#{}里面可以写任意东西,如果不是简单类型则必须写类的属性名
3.查询所有返回结果集的时候,返回值类型也写单个对象的完全限定名

开发Mybatis步骤:

1.写一个conf.xml配置文件(写数据库信息和需要加载的类映射文件)
2.写一个表
3.写对应的类
4.类对应的映射文件(里面写基本的sql语句包括select\inster\delete\update)
5.写一个测试类

Reder reder=Resources.getResourceAsReder("conf.xml");
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reder);
SqlSession session=sessionFactory.openSession();
String statement="类映射文件限定名+id"
Person person=session.selectOne(statement);
session.close();

基于动态代理的Mybatis:

接口中方法的约定:

​ 1.namespace的值,就是接口的全类名(接口和mapper.xml一一对应)

​ 2.方法名和mapper.xml文件中id值相同

​ 3.方法的输入参数和mapper.xml文件中标签的parameterType类型一致

​ 4.方法的返回值和mapper.xml里面的resultType类型一致

匹配的过程:

1.根据接口名找到对应的mapper.xml文件(根据的是namespace=接口全类名)
2.根据接口的方法名找到mapper.xml文件中的SQL标签(方法名=SQL标签ID)

根据以上两点可以保证:当我们调用接口中的方法时
程序能自动定位到某一个Mapper.xml文件中的SQL标签

使用的过程:

1.写一个接口,接口名为xxxMapper,和映射文件中的namespace里面的名字一样,接口里的方法名
就是映射文件中的每个标签的名字,返回值就是resultType的类型(查询全部返回list集合除外)
输入参数就是映射文件中的parameterType的类型
例:

public Student queryStuentByStuno(int stuno);//查询单个学生
public void addstudent(Student student);//增加单个学生
public void deletestudentByStuno(int stuno);//删除学生
public void updatestudentByStuno(Student student);//更新学生
public List<Student> queryAllStudents();//查询所有学生

2.在测试类中:

Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSession sessionFactory=new SqlSessionFactory().build(reader);
SqlSession session =sessionFactory.openSession();
XXXMapper mapper=session.getMapper("接口名.class");
返回值=mapper.接口中的方法(传参);
session.commit();
session.close();

设置别名:(conf.xml里面的标签里面配置)

1.设置单个别名:(设置完别名以后,大小写可以不一样也可以识别)

<typeAliases>
	<!-- 设置单个别名: -->
	<typeAlias type="entity.Student" alias="student"/>
</typeAliases>

2.批量设置别名:设置完别名以后,大小写可以不一样也可以识别)

<typeAliases>
	<!-- 批量设置别名:(可忽略大小写),会将该包中的所有类批量设置别名,别名就是类名(不带包名) -->
	<package name="entity" />
</typeAliases>

ResultMap:

当属性名和字段名不同的时候为了能映射要使用resultmap
1.写一个方法
2.在XXXmapper.xml文件中标签的resultType改成resultmap=“下面配置的resultmap标签的id”
3.在下面配置:

<resultMap type="返回值类型" id="XXXresultmap">
<!-- 分为主键Id和非主键result-->
<id property="id" column="stuno"/>
<!-- <result property="xxxx" column="xxxx"/> -->
</resultMap>

#{}和${}的区别

类型为简单类型(8个基本类型+string):

1.# {可以任意值}, $ {value},其中的标识符只能是value。
2.#{}会自动给String加上’ ’ (自动类型转换),$ { }原样输出,但是适用于动态排序(动态字段)。
3.#{}可以防止sql注入,$ { }不可以防止sql注入。

模糊查询:

1.在mapper文件中的模糊查询sql中…like ‘%${xxxxxx}%’
2.测试类传值直接传一个字符串即可

输入参数为HashMap:

1.将select标签中的parameterType改为HashMap
2.在测试类中new一个<String,Object>Hashmap然后put参数进去,
3.在Mapper的SQL直接根据key获取

输出参数resultType:

1.简单类型(8+String)
2.输出参数为实体类对象类型
3.输出参数为实体类对象类型的集合:虽然输出的是一个集合,但是在resultType还是写单个对象(resultType=“student”)
4.输出参数为Hashmap(通过别名来实现输出类型为hashmap 别名->key)
4.1将XXXMapper.xml中的标签中的resultType=“HashMap”
4.2在接口中写一个方法,返回值是List<HashMap<String,Object>>
5.输出参数为resultMap用于实体类的属性和数据库表的字段不一致(当属性和数据库表的字段不一致时)

a.使用resultMap="xxxresultmap"配置:

1.写一个方法
2.在XXXmapper.xml文件中标签的resultType改成resultmap=“下面配置的resultmap标签的id”
3.在下面配置:

<resultMap type="返回值类型" id="XXXresultmap">
<!-- 分为主键Id和非主键result-->
<id property="id" column="stuno"/>
<!-- <result property="xxxx" column="xxxx"/> -->
</resultMap>
b:使用resultType配置:

1.写一个方法
2.在XXXMapper.xml中标签的sl语句中加上别名
例子:

select id "stuNo" ,name "stuName" from student where id=#{id}

Mybatis动态SQL:

1.(根据判断是否传入了值来进行sql拼接)
使用1=1:

1.在XXXMapper.xml的sql进行动态的拼接,例子:select * from student where 1=1
2.然后判断传值进来的student对象的属性是否有值并且值不是"",需要加标签

select * from student where 1=1
<if test="stuName!=null and !stuName.equals(' ')">
 	and stuname=#{stuName}
</if>
<if test="stuAge!=null and stuAge!=0">
 	and stuage=#{stuAge}
</if>
不使用1=1:

可以对sql进行拼接,加1=1为了拼接上and不会报错

1.在XXXMapper.xml的sql进行动态的拼接,例子:select * from student
2.为了不使用1=1,需要加标签,此标签会对多出来的and处理

<where>
<if test="stuName!=null and !stuName.equals(' ')">
 	and stuname=#{stuName}
</if>
<if test="stuAge!=null and stuAge!=0">
 	and stuage=#{stuAge}
</if>
</where>

注意:标签只会处理第一个if标签中的and,但不会处理之后中的and

2.(查询指定的学号,传入一个数组、集合、对象数组、对象里面的集合属性,然后遍历)

注意!!!!!!!!!:
数组:无论编写代码时传递的是什么参数名,在mapper.xml中parameterType必须用array代替该数组
集合:无论编写代码时传递的是什么参数名,在mapper.xml中parameterType必须用list代替该集合
对象数组:传入一个对象数组,每个对象都有一个学号属性,在mapper.xml中的parameterType必须用Object[]代替该数组,item=“student” 然后拼接处是#{student.stuNo}

传入值为List:

1.在XXXMapper.xml中写一个标签传入参数parameterType是List
2.写一个主查询语句:select * from student where stuno in
3.写一对和标签判断传入List是否为空或者为null

<where>
	<if test="List!=null and List.size>0" >
	</if>
</where>

4.然后遍历

<where>
	<if test="List!=null and List.size>0" >
		<foreach collection="List" open "(" close=")" 
		item="stuNo" separator=",">
		#{stuNo}
		</foreach>
	</if>
</where>
<!-- foreach中的collection代表循环的List(必须为List),open代表拼接的头,
close代表拼接的结束 ,item代表循环指定的单个元素,separator代表每次循环加一个, -->

由此可以拼接出一条sql:select * from student where stuNo in (1,2,3,4,5)

3.(当进行更新操作时,可以判断传入元素有内容时,才进行更新)

例子:update user

java<set>
	<if test="userName!=null and !userName.equals('')">
	user_name = #{userName},
	<if>
	<if test="password!=null and !password.equals('')">
	password = #{password},
	<if>		
</set>

标签作用:当该元素有内容时,生成SQL语句时就加上set语句,当set内容以逗号为结尾时,去掉逗号

标签作用:当该元素有内容时,生成SQL语句时就加上set语句,
当set内容以逗号为结尾时,去掉逗号

4.(当模糊查询的时候可以创建一个变量并将其绑定到上下文中)

1.在select标签中写:

<bind name="userName" value="'%'+name+'%'"/>
	select * from user where username like #{userName}	

意思定义一个userName变量,由name拼接出来
2.接口中的方法在传入的参数前加上@Param(“name”)
例:@Param("name")String name

5.(可以处理sql语句中多余的东西)

标签和where标签一样,但是可以处理sql语句中最后多出来的and
并且有两个属性——prefix:给sql拼接上什么。

prefixOverrides:对开头多出来的什么进行处理
suffixOverrides:对最后多出来的什么进行处理。

例子:

<trim prefix="where" prefixOverrides="and"></trim>

< trim>标签会自动加上where,并且对and进行处理

SQL片段:

我们可以将一些常用的SQL剪切成SQL片段然后进行引用
1.在XXXMapper.xml中写一个标签,其中包含需要存储的SQL片段,用id进行区分
2.在需要引用处写一个进行引用

<include refid="上面sql片段的id"></include>

注意:如果引用的sql片段在另一个mapper.xml中,refid="另一个mapper.xml的namespace+SQL标签的id"

Mybatis一对一:

方式一:使用业务拓展类(不推荐使用)

例子:学生和学生证一对一
1.写一个学生表包含id,stuname ,cardid(外键) ,写一个stucard表包含cardid ,cardinfo
2.在mapper.xml写一个select标签,sql语句是select s.,c. from student s inner join studentcard c
on s.cardid=c.cardid where s.stuno=#{stuNo}
3.写一个学生拓展类StudentBusiness 继承学生类,然后private int cardid,private String cardinfo
4.将mapper.xml里面的resultType=“StudentBusiness”

方式二:使用resultMap(推荐使用)

例子:学生和学生证一对一
1.通过在类中加一个属性,属性是另一个类来建立关系
2.将resultType改为resultMap
3.在mapper.xml写一个select标签,sql语句是select s.,c. from student s inner join studentcard c
on s.cardid=c.cardid where s.stuno=#{stuNo}
4.在下方写resultMap标签,先写主类Student的信息

<resultMap type="Student" id="student_card_map">
<!-- 配置学生的信息-->
	<id property="stuNo" column="stuNo"/>
	<result property="stuName" column="stuName"/>
	<result property="stuAge" column="stuAge"/>
<!-- 一对一时候,对象成员使用association映射 JavaType指定该属性的类型-->
<association property="card" javaType="StudentCard">
	<id property="cardId" column="cardId"/>
	<result property="cardInfo" column="cardInfo"/>
</association>
</resultMap>

5.在接口文件写一个方法:

public Student queryStudentbyStudentcard (int stuNo)

Mybatis一对多(使用resultMap配置):

例子:学生(一)和班级(多)
1.写一个表studentClass班级表包含classId,calssName,写一个student表包含stuno,stuname,classId(外键指向班级表calssid)
2.在mapper.xml写一个select标签,sql语句是select c.,s. from student s inner join studentclass c on
c.classid=s.classid where c.classid=#{classid}
3.将mapper.xml里面的resultMap=“XXX”
4.在下方配置resultMap

<resultMap type="studentClass" id="XXX">
<!-- 因为type的主类是班级,所以先配置班级的信息-->
<id property="classId" column="classId"/>
<result  property="className" column="className"/>
<!-- 配置成员属性学生List ,一对多;属性类型用JavaType 属性的元素类型用ofType -->
<collection property="students" ofType="student">
	<id property="stuNo" column="stuNo"/>
	<result  property="stuName" column="stuName"/>
	<result  property="stuAge" column="stuAge"/>
</collection>
</resultMap>

5.在接口文件写一个方法:

public StudentClass queryClassAndStudents(int classId);

Mybatis的日志:

1.导入log4j.jar
2.在mybatis的conf.xml文件中配置开启日志,在里面进行配置

<setting name="logImpl" value="LOG4J"></setting>

3.新建一个文件log4j.properties 内容:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.新建一个文件log4j.properties 内容:

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

Mybatis延迟加载:

如果不采用延迟加载,查询会将一和多都进行查询,浪费资源–》(立即查询)
如果想要暂时只查询1的一方,而多的一方先不查询而是在需要的时候才进行查询–》(延迟加载)

一对一延迟加载:(查学生时和学生证无关,需要学生证才去查询学生证):

1.将标签下的和标签删了,将sql改成select * from student,
然后配置:

<association select="下面mapper.xml中的namespace+id" column="外键cardId">

2.新建一个mapper.xml,在里面写一个标签,sql:select * from studentCard where cardid=#{cardId}
id=“XXX” parameterType=“int” resultType=“studentCard”
3.在conf.xml关闭立即加载。开启延迟加载
关闭立即加载:

<setting name="aggressiveLazyLoading" value="false"></setting>

开启延迟加载:

<setting name="lazyLoadingEnabled" value="true"></setting>

4.将新建的mapper.xml加入到conf.xml中

Mybatis缓存机制:

一级缓存(缓存在内存中):

Mybatis默认开启一级缓存,当使用同一个sqlsession对象查询同一个数据时,第一次的查询先会去缓存内进行查询,
如果缓存内没有再去数据库进行查询,查询到以后将查询到的内容存放至内存中的sqlsession对象中,当第二次查询
同一个对象时,就直接从内存中进行获取,缓存可以减少对数据库的访问,减少资源消耗,当进行commit操作时,
会将sqlsession对象中的缓存进行清除,当调用sqlsession的close()方法则一级缓存不可用,当调用sqlsession的
clearCache()方法时,缓存将被清空,但对象仍然可以使用 ,当调用了update();delete();insert();方法时都会清理缓存
但是对象仍然可以使用

二级缓存(将对象放入硬盘文件中):
Mybatis自带的二级缓存:

Mybatis默认关闭二级缓存,Mybatis二级缓存是针对namespace而言,而接口产生依赖namespace,mapper对象的产生也依赖于接口。
所以mapper对象的产生依赖于namespace。如果是同一个Sqlsession对象进行多次相同的查询,则直接进入一级缓存查询,
如果不是同一个sqlsession对象(但均来自一个namespace)进行多次相同的查询,则会进入二级缓存进行查询
当执行session.close();方法时会将查询到的结果保存到二级缓存中,当执行session.commit();(增删改会commit)方法时,会将二级缓存清理

开启二级缓存:

1:在conf.xml开启二级缓存:

<setting name="cacheEnabled" value="true"/>
  <!-- 开启二级缓存-->

2.在使用的namespace开启二级缓存:

<cache/>

3.实现二级缓存的实体类要实现序列化接口implements Serializable,如果类中属性包含其他的类,则该类也要实现这个接口

关闭某一个标签的二级缓存:

1.在select标签中加入一个元素userCache="flase"该查询即可关闭二级缓存

清理二级缓存:

1.调用commit();(在增删改的时候调用commit(),清理是为了避免脏数据),在清理二级缓存时,不能是查询自身的commit
2.在select标签中加入元素flushCache=“true”

整合第三方(Ehcache)的二级缓存:

1.需要三个jar:
Ehcache-core.jar
mybatis-Ehcache.jar
slf4j-api.jar
2.编写ehcache配置文件ehcache.xml:

<ehcache>
<!-- 当二级缓存的对象超过内存限制时(缓存对象的个数>maxElementsInMemory的
数量),存放硬盘的路径 -->
<diskStore path="C:\cache"/>
<!-- maxElementsInMemory设置在内存中缓存对象的个数 
eternal设置缓存是否永久不会过期
overflowToDisk:当对象个数超过maxElementsInMemory的时候,是否转移到硬盘中
timeToIdleSeconds:当次访问时间超过该值的时候,将缓存对象失效,单位秒
timeToLiveSeconds:一个缓存对象最多存放的时间(生命周期)
-->
<defaultCache
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"/>
</ehcache>

3.在mapper.xml文件中配置Ehcache:

<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>

在下面可以继续配置ehcache.xml文件中的配置,如果配置是对其进行覆盖

Mybatis逆向工程:

1.表、类、接口、mapper.xml四者密切相关,因此,当知道一个的时候,其他三个可以自动生成
表->生成其他三个
实现步骤:
1.mybatis-generator-core.jar\Mybatis.jar\mysqlconnection.jar
2.逆向工程的配置文件generator

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值