MyBatis
Posted 拇指编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis相关的知识,希望对你有一定的参考价值。
今天这篇推文作者换人啦,作者我跑去吃鸡啦。下面有请我的好友——Guitar Fans。来个大家介绍一下什么是Mybatis
Mybatis是一个持久层的框架,是apache下的顶级项目。该项目目前托管在github下 https://github.com/mybatis/mybatis-3/releases ,下载后解压后目录如下,lib为依赖包,mybatis-3.4.6.jar为核心包。
导入java项目,当然也要导入mysql连接包。
Mybatis让程序员将主要精力放在编写sql语句上,通过mybatis提供的映射方式,自由灵活地生成(半自动化生成,大部分需要程序员编写sql语句)满足需要的sql语句。
Mybatis可以向PreparedStatement中的输入参数自动进行输入映射,将查询结果集映射成java对象(输出映射)。
使用教程
从基本配置文件开始讲起Mybatis注重配置文件和sql的编写,因此我们先了解一下MB的配置文件及其内容。
首先是目录
config源码包存储的是mybatis项目中大部分的配置文件;
db.properties是数据库连接信息;
log4j.properties为该文件可设定日志的输出目的地和输出格式;
SqlMapConfig.xml全局配置文件,该文件配置了数据源,映射文件的位置、别名等信息。
src源码包下
com.fjj.first:junit:测试文件(基本映射测试)
com.fjj.mapper:mapper:映射文件和对应的数据库操作接口
com.fjj.po:pojo:自定义类型
com.fjj.test:junit:测试文件
< 注:以上包和文件的命名可以更改,并非一定要这样命名其他都是项目所需要引用的包 >
接下来详细介绍各个文件的内容
先贴出文件内容
以上是对于java项目开发者所使用的文件内容,在开发环境 log4j.rootLogger 设置为DEBUG,在生产环境中设置为ERROR或者INFO,输出到控制台。
如果要将日志输出到文件中,参考: https://blog.csdn.net/u012506661/article/details/52703057
数据库连接信息配置,此处采用jdbc连接
这里注意一个细节,也是笔者之前在写一个简单的项目时遇到的问题。因为很多人都熟悉了在Java类中写数据库连接字符串,因此在url中设置字符这一段中经常使用 & 作为“与”来使用,那么在调试过程中,会报出以下错误
因为在properties文件中只能使用&来作为与连接。
SqlMapConfig.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>
<!-- 加载属性文件 -->
<properties resource="db.properties">
<propertyname="username" value="123"/>
</properties>
<typeAliases>
<!-- 单个别名定义 -->
<!--<typeAlias type="com.fjj.po.User"alias="User"></typeAlias> -->
<!-- 批量定义包名(推荐),自动扫描其中的类 ,类名首字母大小写均可-->
<package name="com.fjj.po"></package>
</typeAliases>
<!-- 配置mybatis的环境信息,与spring整合,该信息由spring来管理 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManagertype="JDBC"></transactionManager>
<!-- 配置数据源,采用mybatis连接池 -->
<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>
<!-- 映射文件的位置 -->
<!-- 一次加载一个mapper文件-->
<!--<mapper resource="sqlmap/User.xml" />
<mapper resource="mapper/UserMapper.xml"/> -->
<!--通过mapper接口加载文件 -->
<!--加载规范:需要将mapper接口类名和mapper.xml文件映射文件名保持一致,且在一个目录 -->
<!--前提:使用mapper代理 -->
<!--<mapper class="com.fjj.mapper.UserMapper"></mapper>-->
<!--批量加载mapper
指定包名,扫描包下所有mapper接口进行加载(推荐) -->
<package name="com.fjj.mapper"></package>
</mappers>
</configuration>
讲解sqlmapconfig.xml各标签作用
A. properties:加载属性文件,其内含resource属性指明了属性文件名,在之后可以使用${文件名.属性}调用文件中的属性值,在标签内部可以定义单个属性property,如<property name="username" value="123"/>,即文件中的username值为123
B. typeAliases:定义别名,在映射文件需要用到po层下的自定义类,若不定义别名,则每次都要使用路径查询类,如com.fjj.User,定义别名 后可以只用User,简化代码。批量定义别名,只需加入package标签,name 设置为包名称,会自动扫描该包下的所有类名,并作为别名来使用(推荐使用)
C. 有关 transactionManager,
environment的作用可以看下注释在这里不做过多的解释
D. mapper:指明映射文件的加载位置,有三个方法:第一种,一次加载一个mapper文件,在dao层写接口和实现类完成数据库操作,这种方法使得java代码中存在大量模板方法和硬编码;第二种,使用mapper接口加载文件,这里需要mapper接口和映射文件在同一目录下且文件名一致;第三种,注册指定包下的所有映射文件,同样要求mapper接口和映射文件在同一目录且文件名一致(推荐使用)
E. 有关 association,settings,plugins,typeHandlers,objectFactory作用以后介绍
<还是一样的骚操作>
<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fjj.mapper.UserMapper">
<!-- 使用resultMap进行输出映射
type:resultMap最终映射的Java类型
id:resultMap标识符
-->
<resultMap type="User"id="userResultMap">
<!-- id表示查询结果集中的唯一标识
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMap对column和property做一个映射关系 -->
<id column="id_"property="id"></id>
<result column="username_"property="username"></result>
</resultMap>
<select id="findUserByIdResultMap"parameterType="int"resultMap="userResultMap">
select idid_,usernameusername_ from user where id=#{value}
</select>
<!-- 用户信息综合查询
#{userCustom.sex}取出pojo中用户性别
-->
<select id="findUserCount"parameterType="UserQueryVo"resultType="int">
selectcount(*) from user where sex=#{userCustom.sex} and username like '%${userCustom.username}%'
</select>
<select id="findUserByUsername"parameterType="String"resultType="User">
SELECT * FROMUSER WHERE username like '%${value}%'
</select>
<delete id="deleteUser"parameterType="int">
DELETE FROMUSER WHERE id=#{id}
</delete>
</mapper>
贴出以上代码,在下面的mybatis基础项目开发过程中会详细讲映射文件的作用的。
Mybatis开发大概流程如下:
a.创建java项目,导入依赖jar包
b.创建核心配置文件sqlmapconfig.xml
c.创建映射文件UserMapper.xml
d.创建实体类User,根据数据库表字段创建
e.创建mapper接口文件,接口与映射文件名同名,接口方法名与映射文件中配置的sql的id对应
实体类mapper映射文件和mapper接口:
Mapper映射文件namespace指定要映射mapper接口,在文件中select,insert,update,delete标签对应sql语句中的查,增,改,删;
如上所示,id是唯一标识,在与接口中的方法对应,parameterType表示输入值类型,即sql语句执行所需的条件值,resultType表示返回值类型,标签内部定义sql语句。
这里select语句返回的记录可能不止一条,即返回值在java代码中表现为list,但是这里resultType表示单条记录表示的类型,因此这里还是返回user类型。若sql语句的条件没有输入值,则不需要定义parameterType,resultTye也是一样。
标签内部定义sql语句:
select * from user where username like '%${value}%'
中like后面的字符有两种写法:
1. '%${value}%',${}起到拼接字符串作用,使用这种方法拼接sql会有sql注入的风险
这是value为'范'查询的结果
这是value为'OR 1=1 OR'的结果,导致所有用户信息泄露。
2. #{id},#{}起到占位符的作用,这种方法是不存在sql注入的,所以为了安全起见,在实际开发过程中,尽量使用#{}
哪些情况下使用${}拼接不会发生sql注入?
有时候可能需要直接插入一个不做任何修改的字符串到SQL语句中。这时候应该使用${}语法。比如动态sql中的字段名:ORDER BY ${columnName}Mapper 映射文件配置好了以后就要写mapper接口,根据命名空间的定义,命名为UserMapper,接口内方法
<注:接口写好以后不需要写实现类,可以在测试中直接调用>
测试类代码如下:
(划船不靠浆)
package com.fjj.test;
import static org.junit.Assert.*;
import java.io.InputStream;
import java.util.List;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import com.fjj.mapper.UserMapper;
import com.fjj.po.User;
public class UserMapperTest {
privateSqlSessionFactory sqlSessionFactory;
@Before
publicvoid setUp() throws Exception {
//配置代码
Stringresource="SqlMapConfig.xml";
InputStreaminputStream= Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
}
@Test
publicvoid testFindUserByUsername()throwsException{
SqlSessionsqlSession=sqlSessionFactory.openSession();
UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);
List<User>list=userMapper.findUserByUsername("范");
System.out.println(list);
}
}
测试结果如下
可以看出以上输出的列名为username,sex,
birthday,id,与User类的属性名一直,但在实际开发中需要输出的列名不一定与pojo类属性名相同,这个时候就需要使用resultMap进行输出映射,以下面代码为例:
(他咋写怎么多呢)
<!-- 使用resultMap进行输出映射
type:resultMap最终映射的Java类型
id:resultMap标识符
-->
<resultMap type="User"id="userResultMap">
<!-- id表示查询结果集中的唯一标识
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMap对column和property做一个映射关系 -->
<id column="id_"property="id"/>
<result column="username_"property="username"/>
<result column="birthday_"property="birthday"/>
<result column="sex_"property="sex"/>
<result column="address_"property="address"/>
</resultMap>
<select id="findUserByIdResultMap"parameterType="int"resultMap="userResultMap">
select idid_,sex sex_,usernameusername_,birthday birthday_,addressaddress_ from user whereid=#{value}
</select>
resultMap中<id/>是查询结果集的唯一标识,比如User中的id,column为查询出来的列名,property为映射到pojo类型中的属性名,如id_映射到user类中的id<result/>是对普通列的映射定义,比如username,sex,birthday等。
column为查询出来的列名,property是映射到pojo类型中的属性名。清楚这一点后,其他代码基本相同,输出结果如下:
最后,Guitar Fans 写了这么多也不知道让大家有没有理解Mybatis框架。不过这是第一篇,之后会继续推出Mybatis其他文章以及其他Web框架。期待吧!
以上是关于MyBatis的主要内容,如果未能解决你的问题,请参考以下文章