MyBatis入门

<一> MyBatis简介

1.什么是ORM?

ORM(Object-RationalMapping),对象关系映射,它的作用是在关系型数据库和对象之间作一个映射处理,JDBC拥有天生的缺陷,需要手动的完成面向对象的java语言、面向关系的数据库之间数据的转换,代码繁琐无技术含量,影响了开发效率。

相当于在面向对象语言和关系数据库之间搭建一个桥梁。这样我们在具体的操作数据库的时候,只要像平时操作对象一样操作它就可以
了, ORM 框架会根据映射完成对数据库的操作,就不需要再去和复杂的 SQL 语句打交道了。
2.持久化与瞬时状态
  • 瞬时状态
        当创建一个对象后,但是没有存储到数据库中之前的这一段时间状态被称为瞬时态。
  • 持久化状态
        当一个对象被存储到了磁盘的数据库中,该种保存状态被称为持久化状态。
3.事务
  •   事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新    数据库中各种数据项的一个程序执行单 元(unit)
  •   默认情况下,MySQL的事务提交方式是自动提交。每一条SQL语句就是一个独立的事务!

<二>MyBatis环境搭建

  • 下载地址
    https://github.com/mybatis/mybatis-3/releases
  • 中文文档
    https://mybatis.net.cn/
2.1导入依赖
<? xml version = "1.0" encoding = "UTF-8" ?>
< project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi : schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion > 4.0 . 0 </ modelVersion >
< groupId > com . csi </ groupId >
< artifactId > mybatis01 </ artifactId >
< version > 1.0 - SNAPSHOT </ version >
< properties >
< maven . compiler . source > 8 </ maven . compiler . source >
< maven . compiler . target > 8 </ maven . compiler . target >
</ properties >
< dependencies >
<!-- 添加 mybatis 依赖 -->
< dependency >
< groupId > org . mybatis </ groupId >
< artifactId > mybatis </ artifactId >
< version > 3.5 . 7 </ version >
</ dependency >
<!-- 添加数据库依赖 -->
< dependency >
< groupId > mysql </ groupId >
< artifactId > mysql - connector - java </ artifactId >
< version > 8.0 . 23 </ version >
</ dependency >
<!-- 添加测试依赖 -->
< dependency >
< groupId > junit </ groupId >
< artifactId > junit </ artifactId >
< version > 4.12 </ version >
< scope > test </ scope >
</ dependency >
< dependency >
< groupId > org . projectlombok </ groupId >
< artifactId > lombok </ artifactId >
< version > 1.18 . 24 </ version >
</ dependency >
</ dependencies >
</ project >

2.2xml建立

    2.2.1全局配置文件

 

< properties resource = " 属性配置文件的路径 " />
< settings >
< setting name = "" value = "" />
</ settings >
< typeAliaes >
// 将每一个对应的别名进行分别配置
< typeAlias type = " " alias = " 别名 " />
// 包扫描
< package name = " 实体类包名 " />
</ typeAliaes >
< configuration >
< environments default = "development" >
< environment id = "development" >
< transactionManager type = "JDBC" />
< dataSource type = "POOLED" >
< property name = "driver" value = "${driver}" />
< property name = "url" value = "${url}" />
< property name = "username" value = "${username}" />
< property name = "password" value = "${password}" />
</ dataSource >
</ environment >
</ environments >
</ configuration >
  • typeAliaes 
  1. 分别配置
  2. 使用包扫描
       在没有注解的情况下,会使用 JAVABean 的首字母小写的非限定类名来作为它的别名。
<typeAliases>
    <!--给某一个类做别名-->
    <!--<typeAlias type="com.csi.smbms.domain.User" alias="User" />-->
    <!--扫描某一个包,将包中所有类全部自动化命名。规则是将首字母大写!-->
    <package name="com.csi.domain"/>
</typeAliases>

 

 注:所有配置文件都放在resources里

 1.具体配置图片

  • mybatis-config.xml

 

如果想要调用 dev 的环境,则需要在 build 的时候,手动添加对应的环境 id 名称
SqlSessionFactory factory = new SqlSessionFactoryBuilder (). build ( is , "dev" ) ;
jdbc:mysql://localhost:3306/smbms?
serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&useAffectedRows=true
  • 事务管理(transactionManager
        事务管理默认使用的是JDBC 调用,还可以配置其他 (MANAGED) 的使用方式。
  • 数据链接池(dataSource)
        默认采用POOLED ,除此外还可以采用 UNPOOLED( 没有连接池,原生 ) 以及 JNDI 形式。
  • 映射文件加载 
  • 配置包扫描的形式,需要注意,要将dao接口类与mapper映射文件放置在同一个包中。
  • log4j.properties

 

 

  •  jdbc.properties

 

2.2.2映射文件

 

<?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.csi.domain.Role" >
<!--
id: 代表方法名称
resultType :返回的类型
-->
<select id = "list" resultType = "com.csi.domain.Role" >
SELECT * FROM smbms_role
</select>
</mapper>

 

2.2.3日志配置文件

 

<三>MyBatis的生命周期 

3.1 SqlSessionFactoryBuilder

  • 用过即丢,其生命周期只存在于方法体内
  • 可重用其来创建多个 SqlSessionFactory 实例
  • 负责构建SqlSessionFactory,并提供多个build方法的重载

3.2 SqlSessionFactory

  • SqlSessionFactory是每个MyBatis应用的核心
  • 作用:创建SqlSession实例
  • 在创建SqlSession的同时,能够将事务设置为手动的或者是自动的

 SqlSession session = sqlSessionFactory.openSession(boolean autoCommit);

autoCommit:
true|false

 

  • 作用域: Application
  • 生命周期与应用的生命周期相同
  • 单例

        存在于整个应用运行时,并且同时只存在一个对象实例

package com . csi . utils ;
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 class MyBatisUtil {
// 设定一个静态的 SqlSessionFactory 对象
private static SqlSessionFactory sqlSessionFactory ;
  • 在构建该对象时,就会初始化数据连接池DataSource,当openSqlSession时,会将事务管理器创建出来。

3.3SqlSession 

  • 包含了执行SQL所需的所有方法
  • 对应一次数据库会话,会话结束必须关闭
  • 线程级别,不能共享

 

SqlSession session = sqlSessionFactory . openSession ();
try {
// do work
} finally {
session . close ();
}

 

SqlSession 里可以执行多次 SQL 语句,但一旦关闭了 SqlSession 就需要重新创建。
SqlSession 执行对应的 SQL 语句时,会调用 Executor 执行器执行对应的操作。
4.MyBatisUtils
public class MyBatisUtils {
private static ThreadLocal < SqlSession > tl = new ThreadLocal <> () ;
private static SqlSessionFactory sessionFactory ;
static {
InputStream is = null ;
try {
is = Resources . getResourceAsStream ( "mybatis-cfg.xml" );
} catch ( IOException e ) {
throw new RuntimeException ( e );
}
sessionFactory = new SqlSessionFactoryBuilder (). build ( is ) ;
}
public static SqlSession sqlSession () {
SqlSession sqlSession = tl . get ();
if ( sqlSession == null ) {
sqlSession = sessionFactory . openSession () ;
tl . set ( sqlSession );
}
return sqlSession ;
}
public static void closeSqlSession () {
SqlSession sqlSession = tl . get () ;
if ( sqlSession != null ) {
sqlSession . close ();
tl . set ( null );
}
}
}

 

5. SELECT
5.1 基本查询
  • List: SelectList(namespace+id,参数内容)
  • SelectOne:查询一个,SelectOne(namespace+id,参数内容) ;
5.2 模糊查询
  • 解决方案:
         使用字符串拼接形式 '%${ 变量名称 }%'
         使用 concat 方式 concat('%',#{ 变量名称 },'%')
ps: 代码详见下面
  • 多个参数查询
         解决方案 :
                  使用封装对象的形式传输内容
@Test
public void test2() {
SqlSession session = MyBatisUtil.openSession();
// 通过 session 获取到接口
UserInfoMapper userInfoMapper = session.getMapper(UserInfoMapper.class) ;
UserInfo userInfo = new UserInfo() ;
userInfo.setUsername("linyuhui");
userInfo.setGender(1);
userInfo = userInfoMapper.findByManyCondition(userInfo) ;
System.out.println(userInfo);
session.close();
}

 UserInfo findByManyCondition(UserInfo userInfo) ;

 

<select id="findByManyCondition" resultType="userinfo" parameterType="userinfo">
SELECT
*
FROM
userinfo
WHERE
userName = #{username} AND gender=#{gender}
</select>
  •  通过map来进行封装传值

 List<Dept> findByCondition(Map<String,Object> map) ;

<select id = "findByCondition" resultType = "dept" parameterType = "map" >
SELECT * FROM dept WHERE dname = #{dname} and loc = #{loc}
</select>

 

 

a.对象查询 VS map 查询
当查询的条件都是来自于同一张表,在前端,通过类似于 Spring MVC 的框架,能够自动实现数据的封装,此时利用对象封装 参数查询就比较方便。
b.当查询的条件都是来自于不同的表内容,那么此时,要么新建立一个临时对象用于作为查询的参数,最好的形式就是 map 来 实现该功能。
  • 数据库表中的列名与实体类的字段名不一致
        a.解决方案
                a-1.通过给列起别名方式解决
SELECT e.*,d .dname as dnm
FROM
emp e,dept d
WHERE
e .deptno = d .deptno
AND
e .empno = 110111

               a-2.通过ResultMap实现字段映射

<!--
id : 代表当前 resultMap 的名称
type :当前 resultMap 的真实类型
id : 主键映射 property = 实体类字段 ” column = 列名
result : 属性映射
-->
< resultMap id = "emp_result" type = "emp" >
< id property = "empno" column = "empno" />
< result property = "ename" column = "ename" />
< result property = "job" column = "job" />
< result property = "hiredate" column = "hiredate" />
< result property = "sal" column = "sal" />
< result property = "comm" column = "comm" />
< result property = "dnm" column = "dname" />
</ resultMap >
property: 代表实体类中的字段,会自动映射到对应 column 属性值上,因此 column 字段名称必须要和表中的字段保持一致。

b.
resultType VS resultMap
resultType: 返回的是一个对象。当数据库中的字段与实体类中的属性如果不一致,那么就会导致不一致的属性获取的值是
NULL 。同样,如果在查询较为复杂的情况下,例如多表查询,也无法实现一个一一映射性的关系。
resultMap: 如果查询的结果非常复杂,而且出现了数据库中的字段与实体类中的属性不一致的情况,再有想要实现复杂的关系查
( 一对多 多对一等关系 ) 时,使用 resultMap 再合适不过了。
以上二者不能够同时存在。
  •  $#之间的区别(**)
#{} 是预编译处理, ${} 是字符串替换。
Mybatis 在处理 #{} 时,会将 sql 中的 #{} 替换为 ? 号,调用 PreparedStatement set 方法来赋值;
Mybatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
使用 #{} 可以有效的防止 SQL 注入,提高系统安全性
<select id = "findByLike" resultType = "userinfo" parameterType = "string" >
SELECT * FROM smbms_user WHERE userName LIKE '%${str}%'
</select>
<!-- 推荐的形式 -->
<select id = "findByLike" resultType = "User" parameterType = "String" >
SELECT * FROM smbms_user WHERE userName LIKE CONCAT('%',#{userName},'%')
</select>

 List<UserInfo> findByLike(String userName) ;

 

@Test
public void test2() {
SqlSession session = MyBatisUtil.openSession();
// 通过 session 获取到接口
UserInfoMapper userInfoMapper = session.getMapper(UserInfoMapper.class) ;
List<UserInfo> like = userInfoMapper.findByLike(" ");
System.out.println(like.size());
session.close();
}

 

  • Mapper接口形式操作
  1. 接口名称需要与映射配置文件名称相同
  2. 映射配置文件中namespace必须是接口的全名。
  3. 接口中的方法名和映射配置文件中的标签的id一致。
  4. 接口中的返回值类型和映射配置文件中的resultType的指定的类型一致。
  5. 声明一个接口,将接口与对应的映射文件放置在同一个文件夹中,namespace配置需要引用接口名称,接口中的方法名称与映射文件 中的节点id一致,参数类型、返回值类型一致,在调用时,使用SqlSession对象的getMapper(Mapper.class)的形式调用。

 

  • Mapper接口形式的原理
     Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;接口的方法名,就是映射文件中 Mapper 的 Statement的 id 值;接口方法内的参数,就是传递给 sql 的参数。 Mapper 接口是没有实现类的,当调用接口方法时,接口全限名 + 方法名拼接字符串作为 key 值,可唯一定位一个 MapperStatement。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值