Mybatis入门
Mybatis简介
框架
- 未解决一个开放性问题而设计的具有约束性的支撑结构
ORM
- 对象关系映射 为了解决面向对象与数据库的不匹配
映射好处
-
以一定的映射方式,把实体模型和数据库关系的映射
-
ORM框架启动时加载这些映射和数据库配置文件
-
ORM通过对最原生jdbc的封装提供更加便利的操作API
-
Dao通过ORM提供的便捷API以对象的方式操作数据库关系。
Mybatis与jdbc
-
- jdbc重复性代码比较多 ,mybatis 没有jdbc贾琏欲执事
-
- jdbc在封装数据那块比较麻烦,比如查询一条数据 select * from user where id=1,返回值需要在结果集里面进行封装,使用mybatis 自动会封装
-
- jdbc没有缓存支持,mybatis也是有缓存支持
-
- jdbc写sql写到代码里面,sql和代码融合在一起,修改起来不是很方便,mybatis统一维护sql,专门有mapper.xml文件配置
-
- mybatis比较灵活,支持批量操作
Mybatis操作
数据库准备一张表并创建对应的实体类对象
导入相应jar包
准备配置文件mybatis-config.xml 和数据库配置文件 mapper映射文件
<?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"/>
<!--自定义mybatis别名-->
<!-- 环境们 (很多环境的意思)
default:默认使用哪一个环境(必需对应一个环境的id)
-->
<environments default="mysql">
<!--
一个环境 id:为这个环境取唯一一个id名称
-->
<environment id="mysql">
<!--
事务管理 type:JDBC(支持事务)/MANAGED(什么都不做)
-->
<transactionManager type="JDBC"/>
<!-- 数据源, 连接池 type(POOLED):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代表的是相应的ORM映射文件 -->
<mappers>
<mapper resource="com/lx/dao/impl/ProductMapper.xml"/>
</mappers>
</configuration>
数据库配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=....
jdbc.password=....
映射匹配文件.这个映射文件的名称一般叫做 XxxMapper.xml (Xxx代表的是实体类名称)
<?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">
<!--
这个Mapper的主要功能就是写sql
mapper:根
namespace:命令空间 (用来确定唯一) 以前这个是可以不加的,现在必需加
namespace的值,规则的:映射文件XxxMapper.xml所在的包+domain类名+Mapper
-->
<mapper namespace="com.lx.dao.impl.ProductMapper">
<update id="update" parameterType="product">
<!--
select : 这里面写查询语句 update:修改 delete:删除 insert:插入
id:用来确定这条sql语句的唯一以后我们确定唯一,也就是找sql语句 : namespace +.+ id
parameterType : 传入的参数类型 long:大Long _long:小long (具体的对应请参见文档)
resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
-->
<select id="findOne" parameterType="Long" resultType="com.lx.domain.Product">
SELECT * FROM product WHERE id = #{id}
</select>
</update>
</mapper>
CRUD前提得到sqlSession对象
/*InputStream inputStream=Resources.getResourceAsStream ("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder ().build (inputStream);
//获取sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession ();*/
SqlSession sqlSession=MybatisUtils.INSTANCE.openSession ();
//表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
List<Product> products=sqlSession.selectList ("com.lx.dao.impl.ProductMapper.findAll");
由于CRUD重复代码,提取工具类MybatisUtil(枚举单例)
package com.lx.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public enum MybatisUtils {
INSTANCE;
private static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream inputStream=Resources.getResourceAsStream ("mybatis-config.xml");
sqlSessionFactory=new SqlSessionFactoryBuilder ().build (inputStream);
} catch (IOException e) {
e.printStackTrace ();
}
}
public SqlSession openSession(){
return sqlSessionFactory.openSession ();
}
}
Mybatis细节
-
添加时拿到返回的主键
... <!-- parameterType:需要传入我们的对象 useGeneratedKeys: 是否需要主键 keyColumn:主键所在的列 keyProperty:对象中的属性(代表主键的那个属性) --> <insert id="insert" parameterType="com.lx.domain.Product" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> INSERT INTO product (productName, dir_id, salePrice, supplier, brand, cutoff, costPrice) VALUES (#{productName}, #{dir_id}, #{salePrice}, #{supplier}, #{brand}, #{cutoff}, #{costPrice}) </insert> ...
-
mybatis日志
日志框架: 目前开源的日志框架很多,常见的有log4j、logback ,common-logging、slf4j等
这里我们使用log4j 导入相应包过后
配置文件:
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE 屏蔽输出
#日志级别 com.lx自己的包
log4j.logger.com.lx=TRACE
#输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#输出的格式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
日志级别: 优先级从高到底依次为OFF、ERROR、WARN、INFO、DEBUG、TRACE、ALL。
OFF 最高等级的,用于关闭所有日志记录。
ERROR 程序发生错误时,但仍然不影响系统的继续运行。打印错误和异常信息,方便解决问题。
WARN 警告信息,有些信息不是错误信息,但是也要给程序员的一些提示来。
INFO 信息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息来定位和查找问题。
DEBUG 信息对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
TRACE,很低的日志级别,不常用。
ALL 最低等级的,用于打开所有日志记录。
-
mybatis 别名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BbNdpQJB-1572263246515)(C:%5CUsers%5CAdministrator%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20191028193153471.png)]
自定义别名:typeAlias
在mybatis-config.xml中加入以下代码(注意标签顺序否则会保持)
...
<properties resource="db.properties"/>
<!--自定义mybatis别名-->
<typeAliases>
<!-- 单个配置 -->
<typeAlias type="com.lx.domain.Product" alias="product" />
<!-- 包的配置:项目,添加了包之后,默认类名首字母小写就是别名 -->
<package name="com.lx.query" />
</typeAliases>
<!-- 环境们 (很多环境的意思)
default:默认使用哪一个环境(必需对应一个环境的id)
-->
<environments default="mysql">
...
#与$区别
-
'#'MyBatis会把这个表达式使用?(占位符)替换,作为一个sql参数使用:推荐使用
-
$MyBatis会把这个表达式的值替换到sql中,作为sql的组成部分; 把获取到值直接拼接SQL
该方式主要用于程序拼接SQL;
-
除了要拼接sql结构体要用$(是直接拼接sql),其他都用#,因为用#会替换为?,最终通过prepareStament来设置参数,不会有sql注入问题.
动态sql
MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力
批量删除
<!-- delete from product where id in ( ? , ? ) 批量删除:
collection="list":传入的list,相当于map的key,通过list得到传入的整个集合的值;
index="index" :每次循环的索引
item="id" :每次循环的这个值
open="(" :以什么开始
separator=",":分隔符
close=")":以什么结束
[product1,product2,3,4]
in (1,2,3,4)
-->
<delete id="deleteBatch" parameterType="java.util.List">
delete from product where id
in
<foreach collection="list" index="index" item="id" open="("
separator="," close=")">
#{id}
</foreach>
</delete>
批量添加
<!-- 批量插入:
insert into product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id)
values (?,?,?,?,?,?,?) , (?,?,?,?,?,?,?)
parameterType:传入参数是:java.util.List的类型的;
对传入的list进行foreach循环:取出值填入插入的values中:
collection="list":这个不能修改,表示传入的一个list类似于一个key是list,得到传入的list集合
index="index":每一次遍历的序号
item="item":每次遍历的这个对象别名,可以修改
separator=",":每遍历一次后的分隔符
-->
<insert id="insertBatch" parameterType="java.util.List">
insert into
product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id)
values
<foreach collection="list" index="index" item="item"
separator=",">
(#{item.productName},#{item.salePrice},#{item.costPrice},#{item.cutoff},#{item.supplier},#{item.brand},#{item.dir_id})
</foreach>
</insert>
- mybatis 动态sql—>where+if(高级查询)
<select id="selectWF" parameterType="productQuery" resultType="product">
SELECT * FROM product
<where>
<if test="productName!=null" >
and productName like #{productName}
</if>
<if test="brand !=null">
and brand like #{brand}
</if>
</where>
</select>