首页 > 其他分享 >原生mybatis使用细节回顾

原生mybatis使用细节回顾

时间:2022-11-24 15:07:38浏览次数:35  
标签:原生 SqlSessionFactory 回顾 对象 factory SqlSession session mybatis


mybatis笔记

1、${} 和#{}的区别

#{}是获取参数的内容支持,

索引获取;#{0},parameterType可以是int String之类的。

${param1} 获取指定位置的参数;====== #{0}

若是parameterType是People的话,也可以是#{id},但不是通过拼接,而是通过占位符。

最重要的是,SQL是使用的占位符进行控制。

${}是字符串的拼接,不是使用的占位符,寻找的内容默认是通过get/set方法

例如:parameterType的People ,${id} 即可拼接对应的sql语句。

${0} 默认拼接的就是数字0,而不是第一个参数的值。

2、CDATA关系运算符

<![CDATA[ select * from people where id < #{id} ]]>

3、limit运算符

示例:

select * from people limit 1,2; --从第2行开始,找出两行;

mybatis进行分页时,关键字的逗号 ,之前和之后是不允许关系运算的。所以pageSize和PageNumber都必须计算好之后再进行传递;

4、别名的使用

mybatis.xml配置数据库的。

<configuration>
<settings>
<setting name="logImpl" value=LOG4J />
</settings>
<typeAliases>
<typeAlias type="com.pshdhx.pojo.People" alias="People" />
<package name="com.pshdhx.pojo" />
</typeAliases>
</configuration>

配置了别名,即可在mybatis中的resultType和parameterType中使用。

package配置了,那么只写People也可以找的到类。

5、系统内置别名

就是把java.lang.Integer 包装类换成了int的小写;

其他的也换成了消息hashmap等, list,arraylist都是换成了纯小写;

6、mybatis的新增事务

mybatis的自动提交是关闭的,所以需要在新增时,打开自动提交。

每一个sqlSession,都会建立一个对数据库的连接,事务提交的设置,是针对于这个session的。

openSession(true);

setAutoCommit(true);

InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
//利用SqlSession对象进行sql操作

7、mybatis的动态sql

根据不同的条件,执行不同的sql语句。

<if>
1、作为判断;
</if>
<where>
1、去掉标签块里边的第一个and;
2、少写一个where关键字;
3、不用写where 1=1了;
<choose>
1、choose when连用,相当于switch case,只走一个分支就结束。
<when test="accIn != null and accIn !=''">
and accIn = #{accIn}
</when>
<when test="accOut != null and accOut !=''">
and accOut = #{accOut}
</when>
</choose>
</where>

<set>
1、生成set关键字;
2、去掉最后的一个逗号 “,”;
</set>

select * from log
<trim prefix="where" prefixOverrides="and">
1、去掉了最前边的and
2、给前面加了个where
3、千万记住顺序,先去掉,后添加。
4、suffix:在后边添加内容;
5、suffixOverrides:去掉后边的内容;
and accIn = #{accIn}
</trim>
== select * from log where accIn = #{accIn};

<bind name="money" value="'$'+money"/>
<bind name="money" value="'%'+money+'%'"/>
1、如此,传递过来的money,就自动加上了'$'符号;
2、如此,也这样实现模糊查询;
<foreach collection="list" open="(" close=")" separator=",">
1、适用于in的查询;
2、适用于批量新增,比单条语句批量执行效率高;
</foreach>

mybatis中的foreach效率比较低;
factory.openSession(ExecutorType.BATCH);
底层是JDBC的PreparedStatement.addBatch();
<sql id="mysql"></sql>
<select id="">
<include refid="mysql"></include>
</select>

8、ThreadLocal

作用:给线程容器绑定一个对象,只要该线程不变,在随时随地都可以取得到对象。

final ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("测试");
String result = threadLocal.get();

该对象要么是全局的,要么是final(不允许改变)的。一旦改变线程,就无法取出对象。

在此处的作用:SqlSessionFactory的实例化是一个比较耗费性能的过程,所以需要在类加载的时候,就给创建出来。

public class MyBatisUtil {
//factory实例化的过程是一个比较耗费性能的过程.
//保证有且只有一个factory
private static SqlSessionFactory factory;
private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();
static{
try {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取SqlSession的方法
*/
public static SqlSession getSession(){
SqlSession session = tl.get();
if(session==null){
tl.set(factory.openSession());
}
return tl.get();
}

public static void closeSession(){
SqlSession session = tl.get();
if(session!=null){
session.close();
}
tl.set(null);
}
}

我们需要在web.xml中配置下过滤器【被下边filter取缔】

<web-app>
<filter>
<filter-name>opensession</filter-name>
<filter-class>com.pshdhx.filter.OpenSessionInView</filter-class>
</filter>
<filter-mapping>
<filter-name>opensession</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
@WebFilter("/*")
public class OpenSessionInView implements Filter{

@Override
public void init(FilterConfig filterconfig) throws ServletException {
// TODO Auto-generated method stub

}

@Override
public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException {
SqlSession session = MyBatisUtil.getSession();
try {
filterchain.doFilter(servletrequest, servletresponse);
session.commit();
} catch (Exception e) {
session.rollback();
e.printStackTrace();
}finally{
MyBatisUtil.closeSession();
}
}

@Override
public void destroy() {
// TODO Auto-generated method stub

}

}

9、mybatis缓存

在mybatis中,默认sqlSession的缓存开启;

同一个sqlSession对象,调用同一个sql的id语句时,会把第一次调用返回的结果缓存到内存中。

缓存的是一个statement对象。

<select statementType="CALLABLE/PREPARED/STATEMENT">
prepared 是statement的子接口,它把sql注入的问题解决掉了。
callable:调用存储过程
</select>

SqlSessionFactory 缓存,又叫二级缓存,缓存对象扩展了一级,是factory对象。
只需要在 mapper.xml 中添加

如果不写 readOnly=”true”需要把实体类序列化(把内存中的数据,持久化到硬盘上)

当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存
的数据刷(flush)到 SqlSessionFactory (二级)缓存区中

10、resultMap

返回的结果集中包含一个对象;association

<resultMap type="student" id="stuMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="tid" column="tid"/>
<!-- 如果关联一个对象 -->
<association property="teacher"
select="com.pshdhx.mapper.TeacherMapper.selById"
column="tid"></association>
</resultMap>

<select id="selById" resultType="teacher"
parameterType="int">
select * from teacher where id=#{0}
</select>

包含多个对象 使用collection标签,ofType不影响;

<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list" ofType="student"
select="com.bjsxt.mapper.StudentMapper.selByTid"
column="id"></collection>
</resultMap>

辅表联查主表,mybatis自动过滤。

<resultMap type="teacher" id="mymap1">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<collection property="list" ofType="student" >
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>
<select id="selAll1" resultMap="mymap1">
select t.id tid,t.name tname,s.id sid,s.name
sname,age,tid from teacher t LEFT JOIN student s on
t.id=s.tid;
</select>

只会生成两个teacher对象,每个teacher对象里边有若干个student。归根到底:

mybatis可以通过主键判断该对象是否被加载过,如果被加载过,那么就不需要创建新的对象;否则,就创建新的对象。

11、关于mybatis中代码解读

LogMapper logMapper = session.getMapper(LogMapper.class);
logMapper.selectAll();//此为接口代理的方法
//未获取到接口对象之前的操作
session.selectList("com.pshdhx.mapper.logMapper.selAll");

接口不能实例化,怎么能调用接口的方法呢?原因是使用了代理模式。proxy。

在mybatis.xml中提前配置好了全路径的package的扫描包,那么直接使用mapper接口类的方法即可。

文字解释
1、在 MyBatis 运行开始时需要先通过 Resources 加载全局配置文件;

2、下面需要实例化 SqlSessionFactoryBuilder 构建器。帮助 SqlSessionFactory 接口实现类 DefaultSqlSessionFactory;

3、在实例化 DefaultSqlSessionFactory 之前需要先创建 XmlConfigBuilder解析全局配置文件流,并把解析结果存放在 Configuration

中。之后把Configuratin 传递给 DefaultSqlSessionFactory。到此 SqlSessionFactory 工厂创建成功。

4、由 SqlSessionFactory 工厂创建 SqlSession.每次创建 SqlSession 时,都需要由 TransactionFactory 创建 Transaction。

对象,同时还需要创建 SqlSession 的执行器 Excutor,最后实例化DefaultSqlSession,传递给 SqlSession 接口。

5、根据项目需求使用 SqlSession 接口中的 API 完成具体的事务操作。

如果事务执行失败,需要进行 rollback 回滚事务。

如果事务执行成功提交给数据库.关闭 SqlSession。


标签:原生,SqlSessionFactory,回顾,对象,factory,SqlSession,session,mybatis
From: https://blog.51cto.com/u_15890333/5883986

相关文章