mybatis概念
概念:一个持久层框架
作用:ORM将sql语句映射成实体类
-
特点:
- 巧灵活
- 半自动化
- 使用与中小型项目的开发
mybatis入门
1、创建mybatis-config.xml文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/bank?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
2、创建映射文件UserMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="user"> <!--命名空间SqlSession调用时用-->
<select id="selectUser" resultType="com.hemi.mybatis.bean.User"> <!--id名称标示一条sql语句 resultType 返回bean对象类型-->
select * from user where uid=1;
</select>
</mapper>
3、建立mybatis-config.xml与 UserMapper.xml连接 在mybatis-config.xml标签configuration里加
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
4、获取xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
5、创建SqlSessionFactory
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
6、获取SqlSession
SqlSession sqlSession = factory.openSession();
7、调用SqlSession的selectOne(命名空间.id名称);
Object object = sqlSession.selectOne("user.selectUser");
8、关闭SqlSeesion
sqlSession.close();
增删改
增
![Uploading 2_535075.png . . .]
<insert id="insertUser" parameterType="com.hemi.mybatis.bean.User">
<!-- 通过#{属性名}来获取对象的值 -->
insert into user (username,password) values(#{username},#{password});
</insert>
改
<update id="updateUser" parameterType="com.hemi.mybatis.bean.User">
update user set username=#{username},password=#{password} where uid=#{uid};
</update>
删
![Uploading 3_546596.png . . .]
<delete id="deleteUser" parameterType="int">
delete from user where uid=#{value};
</delete>
Mapper接口开发
一、定义一个接口
public interface TypeMapper {
Type selectType(int typeid);
}
二、定义一个mapper.xml映射文件
mapper文件的要求:
- namespace的值就是对象接口的全类名,并且类名和xml文件名保持一致
- id的值就是抽象方法
- resultType的值必须和抽象方法的返回值一致
- parameterType的值和抽象方法的参数类型一致
注意 mapper.xml文件的约束是mapper.dtd,不是config.dtd
三、使用
将mybatis入门步骤中的步骤六改为如下代码:
TypeMapper mapper=sqlSession.getMapper(TypeMapper.class);
Type type=mapper.selectType(1);
动态sql
if
SELECT * FROM good INNER JOIN type ON good.type = type.typeid where 1=1
<if test="gname !=null and gname !=''">
and gname like concat('%',#{gname},'%');
</if>
注意:
1、字符串的拼接建议使用concat来代替$
{}
2、判断条件中获取数据不用加#{},与el表达式不一样
where
作用where可以自动去除第一个and
<where>
<if test="gname !=null and gname !=''">
and gname like concat('%',#{gname},'%')
</if>
<if test="typename !=null and typename!=''">
and typename like concat('%',#{typename},'%')
</if>
</where>
;
choose when otherwise
作用:组合使用,相当于if else if else
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
;
set
update good
<set>
<if test="gname!=null and gname!=''">
gname=#{gname},
</if>
<if test="gprice!=null and gprice!=''">
gprice=#{gprice}
</if>
</set>
where gid=#{gid};
trim
作用:去除多余字符串
两种常见的用法
1、where and
prefix:字首 prefixOverrides:去除第一个指定的字符串
select * from good
<trim prefix="where" prefixOverrides="and|or">
<!--添加where在前面,并且去除第一个and-->
<if test="gname !=null and gname !=''">
and gname like concat('%',#{gname},'%')
</if>
<if test="typename !=null and typename!=''">
and typename like concat('%',#{typename},'%')
</if>
</trim>
;
2、set
prefix:字首 suffixOverrides:去除最后指定的字符串
update good
<trim prefix="set" suffixOverrides=",">
<!--添加set在前面,并且去除最后一个,-->
<if test="gname!=null and gname!=''">
gname=#{gname},
</if>
<if test="gprice!=null and gprice!=''">
gprice=#{gprice},
</if>
</trim>
;
foreach
作用:动态循环拼接sql部分内容
1、open代表在集合前面添加的字符串
2、close代表在集合后面添加的字符串
3、separator代表集合分割使用的字符串
4、collection代表被循环的集合,值可以是list、map、array
5、常见用法,in的语句
<select id="selectGoodByGid" parameterType="list" resultType="Good">
select gid,gname,gprice,count,type typeid from good
<where>
gid in
<foreach item="item" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</where>
</select>
;
resultMap
作用:
1、可以将表字段与javabean对象属性名进行映射 2、将映射抽取出来,可以给多个statement所使用
<!-- type:最终返回的数据类型 id:resultMap的名称 -->
<resultMap type="Good" id="GoodResultMap">
<!-- 建议将主键设置为id -->
<id column="good_id" property="gid"/>
<!-- 通过result将数据库字段与java对象的属性进行一一映射 -->
<result column="good_name" property="gname"/>
<result column="good_price" property="gprice"/>
<!--
下面的映射可以不用写,因为mybatis中默认设置autoMappingBehavior为PARTIAL,局部自动映射,但是属性名必须和字段名一致
-->
<!-- <result column="count" property="count"/> -->
</resultMap>
;
映射的原理
1、先拿到type指定的类的class
2、通过newInstance创建对象
3、获取property中属性名,通过反射的方式调用对应的set()方法
4、调用方法的invoke()方法,将column的值赋值进去
5、返回封装好的对象
关联嵌套结果(resultMap与resultMap相互嵌套)
<resultMap type="Good" id="GoodResultMap">
<id column="good_id" property="gid"/>
<result column="good_name" property="gname"/>
<result column="good_price" property="gprice"/>
<!-- 一对一的映射关系,选择association -->
<!-- 内部嵌套 -->
<association property="type" javaType="Type">
<id column="typeid" property="typeid"/>
<result column="typename" property="typename"/>
</association>
</resultMap>
;
上面的association部分可以改造为<association property="type" javaType="Type" resultMap="TypeResultMap">,然后使用外部嵌套
<!-- resultMap外部嵌套 -->
<resultMap type="Type" id="TypeResultMap">
<!-- 建议将主键设置为id -->
<id column="typeid" property="typeid"/>
<result column="typename" property="typename"/>
</resultMap>
;
关联嵌套查询
<resultMap type="Good" id="GoodResultMap1">
<id column="good_id" property="gid"/>
<result column="good_name" property="gname"/>
<result column="good_price" property="gprice"/>
<!--column:要传递给下面的statement的参数-->
<!--javaType:该association返回的数据类型-->
<!--select:另一个查询语句的statementId-->
<association property="type" javaType="Type" select="selectTypeByTypeId" column="type"/>
</resultMap>
<select id="selectTypeByTypeId" resultType="Type">
select * from type where typeid=#{value}
</select>
;
集合嵌套结果
<colleciton property="javabean中的属性名" javaType="List" ofType="list集合中的元素类型">
<id column="主键字段名" property="元素类型的属性名"/>
<result column="字段名" property="元素类型的属性名"/>
</colleciton>
;
集合嵌套查询
<colleciton property="javabean中的属性名" javaType="List" ofType="list集合中的元素类型" select="selectUser" column="uid"/>
<select id="selectUser" resultMap="User">
select * from user where uid=#{value}
</select>
;
在主配置文件中配置
<settings>
<!-- 虽然默认是 PARTIAL,但是建议写上-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
;
缓存
一级缓存(同一个SqlSession中执行同一个statement)
默认开启
二级缓存(同一个namespace中,不同SqlSession执行同一个statement)
配置 1、setting中设置cacheEnabled="true" 2、mapper中添加<cache> 3、statement中添加useCache="true" 4、调用session.close()时候才将数据写入二级缓存 5、用到的实体类要实现Serializable接口