MyBatis是一个数据持久层(ORM)框架,在实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。
MyBatis介绍
与传统JDBC的比较
配置文件
配置文件头文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
方法
1、< settings> 全局配置
2、 < typeAliases>给类取别名
3、< environments>配置数据库默认环境
3.1配置数据库环境
3.2使用JDBC事务管理
3.3使用数据库连接池
4、< mappers>加载orm映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局配置 -->
<settings>
<!-- 设置数据库字段下划线跟类对象驼峰命名映射转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 配置控制台输出sql日志 -->
<setting name="logImpl" value="stdout_logging"/>
</settings>
<typeAliases>
<!-- 给类取别名 -->
<!--<typeAlias type="com.entor.entity.User" alias="User"/>-->
<!-- 包下的所有类以简写类名作为别名 -->
<package name="com.entor.entity"/>
</typeAliases>
<!-- 配置数据库默认环境,支持多种环境 -->
<environments default="mysql">
<!-- 配置数据库环境,id唯一标识 -->
<environment id="mysql">
<!-- 使用JDBC事务管理 -->
<transactionManager type="JDBC"/>
<!-- 数据源使用池化技术,即使用数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/jsd2107?useUnicode=true&characterEncoding=utf-8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载orm映射文件 -->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
映射文件
映射文件头文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
方法
namespace不能为空,可以是任何值用来区分不同的映射对象,不同的映射文件值不能一样
面向接口时,填写接口的全限定名
< mapper namespace=“Xxx.xx.xx”>
sql语句接收一个参数,#{任意字符}只是一个占位符,可以填写任意字符
parameterType属性可写可不写,如果写了类型,那调用是必须传递对应类型的参数,否则报错作为查询语句
resultType必须要指定放回类型,用来封装查询到的字段值,通过反射把查询到的字段调用对象的set方法注入到对象属性中
sql语句需要接收多个参数,可以把多个参数封装到一个map中,#{pageNum}意思是调用map中pageNum的值
sql语句需要接收多个参数,可以把多个参数封装到一个对象中,#{name}意思是调用对象中getName方法获取到name的值
useGeneratedKeys 获取自动增长的主键值
keyColumn 数据库主键的列自动名称
keyProperty 数据库主键对应类对象属性名称
三个属性作用是把新增记录的id主键输入到对象的id中
#{}和${}符号的区别:
前者是占位符,传递参数是字符串会添加一堆单引号,可以防止sql注入攻击;
后者是直接拼接参数,参数是字符串不会加单引号,有sql注入风险
简单sql
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace不能为空,可以是任何值用来区分不同的映射对象,不同的映射文件值不能一样 -->
<mapper namespace="com.entor.dao.UserDao">
<sql id="common">
id,name,username,password,sex,age,birthday,create_time
</sql>
<!--<select id="queryById" parameterType="int" resultType="com.entor.entity.User">
select * from user where id = #{id}
</select>-->
<!--<select id="queryById" parameterType="int" resultType="com.entor.entity.User">
select id,name,username,password,sex,age,birthday,create_time from user where id = #{id}
</select>-->
<!-- sql语句接收一个参数,#{任意字符}只是一个占位符,可以填写任意字符
parameterType属性可写可不写,如果写了类型,那调用是必须传递对应类型的参数,否则报错
作为查询语句,resultType必须要指定放回类型,用来封装查询到的字段值,
通过反射把查询到的字段调用对象的set方法注入到对象属性中
-->
<select id="queryById" resultType="User">
select <include refid="common"/> from user where id = #{id}
</select>
<!-- sql语句需要接收多个参数,可以把多个参数封装到一个map中,#{pageNum}意思是调用map中pageNum的值-->
<select id="queryByPage" parameterType="map" resultType="User">
select id,name,username,password,sex,age,birthday,create_time
from user order by id limit #{pageNum},#{pageSize}
</select>
<!-- sql语句需要接收多个参数,可以把多个参数封装到一个对象中,#{name}意思是调用对象中getName方法获取到name的值
useGeneratedKeys 获取自动增长的主键值
keyColumn 数据库主键的列自动名称
keyProperty 数据库主键对应类对象属性名称
三个属性作用是把新增记录的id主键输入到对象的id中
-->
<insert id="add" parameterType="User" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into user(name,username,password,sex,age,birthday,create_time)
value (#{name},#{username},#{password},#{sex},#{age},#{birthday},now())
</insert>
<update id="update" parameterType="User">
update user set
name=#{name},
username=#{username},
password=#{password},
sex=#{sex},
age=#{age},
birthday=#{birthday}
where id =#{id}
</update>
<delete id="deleteById">
delete from user where id=#{id}
</delete>
<!--
#{}和${}符号的区别:前者是占位符,传递参数是字符串会添加一堆单引号,可以防止sql注入攻击;
后者是直接拼接参数,参数是字符串不会加单引号,有sql注入风险
-->
<delete id="deleteByIds">
<!-- 批量删除方式一:直接sql参数拼接 -->
<!-- delete from user where id in (${ids})-->
<!-- 批量删除方二:生成动态sql -->
delete from user where id in
<!-- 接收array数组类型的参数,遍历数组的每一个元素,id值数组中每一个元素 -->
<foreach collection="array" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
<insert id="addMore">
insert into user(name,username,password,sex,age,birthday,create_time)value
<foreach collection="list" separator="," item="user">
(#{user.name},#{user.username},#{user.password},#{user.sex},#{user.age},#{user.birthday},now())
</foreach>
</insert>
<select id="getTotal" resultType="int">
select count(*) from user
</select>
</mapper>
动态sql
<mapper namespace="user">
<insert id="add">
insert into user(
<if test="name!=null and name!=''">
name,
</if>
<if test="username!=null and username!=''">
username,
</if>
<if test="password!=null and password!=''">
password,
</if>
<if test="sex!=null">
sex,
</if>
<if test="age!=null">
age,
</if>
<if test="birthday!=null and birthday!=''">
birthday,
</if>
create_time
) values(
<if test="name!=null and name!=''">
#{name},
</if>
<if test="username!=null and username!=''">
#{username},
</if>
<if test="password!=null and password!=''">
#{password},
</if>
<if test="sex!=null">
#{sex},
</if>
<if test="age!=null">
#{age},
</if>
<if test="birthday!=null and birthday!=''">
#{birthday},
</if>
now()
)
</insert>
<update id="update">
update user
<!--set标签会自动去掉多余的逗号-->
<set>
<if test="name!=null and name!=''">
name = #{name},
</if>
<if test="username!=null and username!=''">
username = #{username},
</if>
<if test="password!=null and password!=''">
password = #{password},
</if>
<if test="sex!=null">
sex = #{sex},
</if>
<if test="age!=null">
age = #{age},
</if>
<if test="birthday!=null and birthday!=''">
birthday = #{birthday},
</if>
</set>
where id = #{id}
</update>
<select id="queryByParam" resultType="User">
select * from user
<!--where标签会自动去掉多余的and,or-->
<where>
<if test="name!=null and name!=''">
<!--方式一:在调用时候参数两侧加%号-->
<!--name like #{name}-->
<!--方式二:直接使用${}拼接参数,有sql注入攻击风险-->
<!--name like '%${name}%'-->
<!--方式三:使用mysql系统函数concat拼接字符串,推荐使用-->
and name like concat('%',#{name},'%')
</if>
<if test="username!=null and username!=''">
and username like concat('%',#{username},'%')
</if>
<if test="sex!=null">
and sex = #{sex}
</if>
</where>
</select>
</mapper>
读取操作
1、加载MyBtis核心配置文件
2、创建SqlSessionFactory工厂类,相当于一个数据库实例对象
3、获取SqlSession会话对象,相当于jdbc中的Connection连接对象
4、执行数据操作
5、关闭会话连接
查询单个对象用selectOne,集合用selectList
public static void main(String[] args) {
try {
//加载mybatis核心配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//创建SqlSessionFactory工厂类,相当于一个数据库实例对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
//获取SqlSession会话对象,相当于jdbc中的Connection连接对象
SqlSession session = sqlSessionFactory.openSession();
//执行数据操作
User user = session.selectOne("com.entor.entity.User.queryById", 100);
System.out.println(user);
//关闭会话连接
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
面向接口方式
面向接口方式,不需要写实现类,mybatis会根据接口生成代理实现类对象
xml命名空间就必须时接口的全限定名
读取操作与xml方式相同