MyBatis技术总结
-
什么是MyBatis?
MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或注解进行配置和原始映射,用以将接口和Java的对象映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。它可以通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中
-
MyBatis中的主要组成部分
SqlSessionFactory:SqlSessionFactory是mybatis的关键对象,它是单个数据库映射关系经过编译后的内存镜像,SqlSessionFactory可以通过SqlSessionFactoryBuild对象类获取,而SqlSessionFactoryBuild则可以从xml配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例,每一个mybatis的应用程序都以一个SqlSessionFactory对象的实例为核心,sqlSessionFactory也是线程安全的,SqlSessionFactory一旦被创建,在应用执行期间都存在,不宜重复创建多次,推荐使用单例模式,SqlSessionFactory是创建SqlSession的工厂。
SqlSessionFactory创建代码示例:
private static final String CONFIG = "mybatis-config.xml"; //配置文件 private static SqlSessionFactory sqlSessionFactory; //SqlSessionFactory对象 private static final Class<MyBatisUtils> CLASS_LOCK = MyBatisUtils.class; //类级别锁 static { //初始化 initSqlSessionFactory(); } //私有的构造方法,保证MyBatis工具类不会被实例化 private MyBatisUtils() { } private static SqlSessionFactory initSqlSessionFactory() { if (sqlSessionFactory == null) { synchronized (CLASS_LOCK) { try (InputStream inputStream = Resources.getResourceAsStream(CONFIG)) { sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } } return sqlSessionFactory; }
SqlSession:SqlSession也是mybatis中的重要对象,是持久化操作的独享。类似于jdbc中的Connection,它是应用程序与持久层之间执行互操作的一个单线程对象,也是Mybatis执行持久化操作的关键对象,SqlSession对象完全包含以数据库为背景的所执行SQL操作方法。底层封装了JDBC连接,可以用SqlSession的实例对来执行被映射的SQL语句,每个线程有他自己的SqlSession实例,SqlSession的实例不能被共享,SqlSession也不是线程安全的,绝对不能将SqlSession实例的引用放在任何类型的管理范围中,使用完SqlSession之后关闭Session很重要,放在finally块来关闭它。
SqlSession创建代码示例:
public static SqlSession openSqlSession() { if (sqlSessionFactory == null) { initSqlSessionFactory(); } return sqlSessionFactory.openSession(); } ```
-
MyBatis配置
- 设置(settings)
主要作用:MyBatis框架运行规则配置(例如:加日志)
设置(settings)代码示例:
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
- 类型别名(typeAliases)
主要作用:设置别名(为实体类设置别名)
类型别名(typeAliases)代码示例:
<typeAliases> <!-- typeAlias:为某个java类型起别名 type:指定要起别名的类型全类名;默认别名就是类名小写; alias:执行新的别名 --> <typeAlias type="com.apesource.entity.Employee" alias="Employee"/> <!-- package:为某个包下的所有类批量起别名 name:指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名【类名小写】) --> <package name="com.apesource.entity"/> <!-- 批量起别名的情况下,使用@Alias注解为某个类型指定新的别名 --> </typeAliases>
- 环境配置(environments)
主要作用:用于配置MyBatis的开发环境。mybatis可以配置多种环境,default指定使用某种环境。
环境配置(environments)代码示例:
<environments default="development"> <!-- 环境1(开发) --> <environment id="development"> <!-- 事务管理器:采用JDBC事务 --> <transactionManager type="JDBC" /> <!-- 数据源(数据库连接池) --> <!-- type设置为pooled,启动数据库连接池 --> <dataSource type="POOLED"> <!-- 数据库连接参数 --> <property name="driver" value="${driver_class}" /> <property name="url" value="${jdbc_url}" /> <property name="username" value="${db_username}" /> <property name="password" value="${db_password}" /> </dataSource> </environment> </environments>
- 映射器(mappers)
主要作用:将sql映射注册到全局配置中
映射器(mappers)代码示例:
<mappers> <!-- SQL映射文件 --> <mapper resource="com/apesource/dao/mapper/AnswerRecordMapper.xml" /> </mappers>
-
MyBatis XML 映射器
1.常用节点作用总结
- select :映射查询语句
- update:映射更新语句
- delete:映射删除语句
- insert:映射插入语句
2.常用属性作用总结
- id 属性:命名空间中唯一的标识符,可以被用来引用这条语句
- resultType 属性:查询语句返回结果类型的完全限定名或别名
- parameterType 属性:指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型、对象、HashMap。
- useGeneratedKeys属性:开启主键回填
- keyProperty属性:设置用于保存主键值的属性名称
3.常见SQL映射示例
示例1:普通增加
<insert id="insertAnswerRecord" parameterType="AnswerRecord" useGeneratedKeys="true" keyProperty="recordId"> insert into answer_record(respondent,question,right_answer,submit_answer,submit_datetime) values(#{respondent},#{question},#{rightAnswer},#{submitAnswer},#{submitDatetime}) </insert>
int insertAnswerRecord(AnswerRecord answerRecord);
示例2:批量增加
<insert id="insertAnswerRecordBatch" parameterType="list" useGeneratedKeys="true" keyProperty="recordId"> INSERT INTO answer_record(respondent,question,right_answer,submit_answer,submit_datetime) VALUES <foreach collection="list" item="record" separator=","> { #{record.respondent}, #{record.question}, #{record.rightAnswer}, #{record.submitAnswer} now() } </foreach> </insert>
int insertAnswerRecordBatch(List<AnswerRecord> answerRecordList);
示例3:普通删除
<delete id="deleteAnswerRecord"> delete from answer_record where record_id = #{recordId} </delete>
int deleteAnswerRecord(int recordId);
示例4:批量删除
<delete id="deleteAnswerRecordBatch" parameterType="list"> DELETE FROM answer_record WHERE record_id IN <foreach collection="list" item="rid" separator="," open="(" close=")"> #{rid} </foreach> </delete>
int deleteAnswerRecordBatch(List<Integer> recordIdList);
示例5:动态修改
<update id="updateAnswerRecord" parameterType="AnswerRecord"> update answer_record <set> <if test="respondent !=null">respondent = #{respondent},</if> <if test="question!=null">question = #{question},</if> <if test="rightAnswer !=null">right_answer = #{rightAnswer},</if> <if test="submitAnswer !=null">submit_answer = #{submitAnswer},</if> submit_datetime=now() </set> where record_id = #{recordId} </update>
int updateAnswerRecord(AnswerRecord answerRecord);
示例6:动态查询
<select id="listAnswerRecordByCondition" resultType="AnswerRecord" parameterType="AnswerRecord"> SELECT record_id AS recordId, respondent, question, right_answer AS rightAnswer, submit_answer AS submitAnswer, submit_datetime AS submitDatetime FROM answer_record <where> <if test="respondent != null"> AND respondent = #{respondent} </if> <if test="question != null"> AND question LIKE concat('%',#{question},'%') </if> <if test="rightAnswer != null"> AND right_answer = #{rightAnswer} </if> <if test="submitAnswer != null"> AND submit_answer = #{submitAnswer} </if> </where> </select>
List<AnswerRecord> listAnswerRecordByCondition(AnswerRecord condition);
示例7:查询结果封装为Map
<select id="countAnswerRecordDataByRespondent" resultType="map" > select count(record_id) as countAll, (select count(record_id) from answer_record where respondent = #{respondent} and right_answer = submit_answer) as rightAnswer, (select count(record_id) from answer_record where respondent = #{respondent} and right_answer != submit_answer) as errorAnswer from answer_record where respondent = #{respondent} </select>
Map<String,Integer> countAnswerRecordDataByRespondent(String respondent);