Mybatis

Mybatis相关配置、 常用API、sqlMapConfig详解、 mapping详解、mybatis注解

  1. Mybatis是什么?
  2. Mybatis的核心组件
  3. Mybatis的动态sql
  4. Mybatis中的Mapper中的常见标签(挑常见的标签给面试官阐述)
  5. Mybatis中的Dao接口的工作原理?(了解)
  6. Dao接口中的方法可以重载吗? 不可以
    不同映射文件xml中的id值可以重复吗?不能
  7. Mybatis中#和$的区别是什么?
  8. Mybatis的缓存机制
  9. Mybatis的接口绑定是什么?有哪些实现方式?

在这里插入图片描述

JDBC

jdbc的原始方法(未经封装)实现查询数据库表记录

public static void main(String[] args) {
	Connection connection = null;
	PreparedStatement preparedStatement = null;
	ResultSet resultSet = null;

	try {
		// 加载数据库驱动
		Class.forName("com.mysql.jdbc.Driver");

		// 通过驱动管理类获取数据库链接
		connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "123");
		// 定义sql语句 ?表示占位符
		String sql = "select * from user where username = ?";
		// 获取预处理statement
		preparedStatement = connection.prepareStatement(sql);
		// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
		preparedStatement.setString(1, "admin");
		// 向数据库发出sql执行查询,查询出结果集
		resultSet = preparedStatement.executeQuery();
		// 遍历查询结果集
		while (resultSet.next()) {
			System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		// 释放资源
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (preparedStatement != null) {
			try {
				preparedStatement.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Mybatis

在这里插入图片描述
MyBatis 简介
1) MyBatis 是支持定制化 SQL、 存储过程以及高级映射的优秀的持久层框架
2) MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
3) MyBatis可以使用简单的XML或注解用于配置和原始映射, 将接口和Java的POJO(Plain
Old Java Objects, 普通的 Java 对象) 映射成数据库中的记录

HelloWorld

官方文档
1 导入 MyBatis 框架的 jar 包、 Mysql 驱动包、 log4j 的 jar 包

2 导入 log4j 的配置文件(参考 MyBatis 的官网手册–>日志)

3 创建 MyBatis 的全局配置文件(参考 MyBatis 的官网手册)
mybatis-config.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><!-- 数据库连接环境的配置 -->
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="dbc:mysql://localhost:3306/mybatis_2020"/>
        <property name="username" value="root"/>
        <property name="password" value="123"/>
      </dataSource>
    </environment>
  </environments>
  <!-- 引入SQL映射文件,Mapper映射文件 -->
  <mappers>
    <mapper resource="EmployeeMapper.xml"/>
  </mappers>
</configuration>

4 创建 Mybatis 的 sql 映射文件
EmployeeMapper.xml

<?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 namespace="com.atguigu.mybatis.EmployeeMapper">
<!-- 
namespace:名称空间;指定为接口的全类名
id:唯一标识
resultType:返回值类型
#{id}:从传递过来的参数中取出id值

public Employee getEmpById(Integer id);
 -->
	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee">
		select id,last_name lastName,email,gender from tbl_employee where id = #{id}
	</select>
</mapper>

5 测试

public class MyBatisTest {
	
	public SqlSessionFactory getSqlSessionFactory() throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		return new SqlSessionFactoryBuilder().build(inputStream);
	}
	
@Test
	public void test() throws IOException {

		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		SqlSession session = sqlSessionFactory.openSession();
		try {
			Employee employee = session.selectOne(
			//select0ne方法用于执行查询查询返回的结果只有-条记录的sq1语句
			//第一个参数是你要执行的sq1语句(Mapper配置文件 名称空间.id)
			//第二个参数,是你要执行的sq1语句的对应参数值
					"com.atguigu.mybatis.EmployeeMapper.getEmpById", 1);
			System.out.println(employee);//实现查询操作
		} finally {
			session.close();
		}
	}
@Test
	public void test01() throws IOException {
		// 1、获取sqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		// 2、获取sqlSession对象
		SqlSession session = sqlSessionFactory.openSession();
		try {
			// 3、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
			EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
			Employee employee = mapper.getEmpById(1);
			System.out.println(mapper.getClass());
			System.out.println(employee);
		} finally {
			session.close();
		}
	}

通过Mapper 接口开发 MyBatis HelloWorld

  1. 编写 Mapper 接口
public interface EmployeeMapper {
	public Employee getEmployeeById(Integer id );
}
  1. 完成两个绑定

1 Mapper 接口与 Mapper 映射文件的绑定 在 Mppper 映射文件中的标签中的 namespace
中必须指定 Mapper 接口 的全类名
2 Mapper 映射文件中的增删改查标签的 id 必须指定成 Mapper 接口中的方法名

  1. 获取 Mapper 接口的代理实现类对象
@Test
public void test() throws Exception{
	String resource = "mybatis-config.xml";
	InputStream inputStream =
			Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory =
			new SqlSessionFactoryBuilder()
				.build(inputStream);
	SqlSession session =
			sqlSessionFactory.openSession();
try {
	//Mapper接口:获取Mapper接口的 代理实现类对象
	EmployeeMapper mapper =
		session.getMapper(EmployeeMapper.class);
	Employee employee =
		mapper.getEmployeeById(1);
	System.out.println(employee);
} finally {
	session.close();
	}
}

MyBatis 全局配置文件

在Eclipse中引入XML的dtd约束文件,方便编写XML的时候有提示
在这里插入图片描述

configuration 配置
properties 属性
settings 设置
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
databaseIdProvider 数据库厂商标识
mappers 映射器

properties 属性

  1. 可外部配置且可动态替换的, 既可以在典型的 Java 属性文件中配置, 亦可通过 properties 元素的子元素来配置
<properties>
	<property name="driver" value="com.mysql.jdbc.Driver" />
	<property name="url"
	value="jdbc:mysql://localhost:3306/test_mybatis" />
	<property name="username" value="root" />
	<property name="password" value="123" />
</properties>
  1. 然而 properties 的作用并不单单是这样, 你可以创建一个资源文件, 名为jdbc.properties 的文件,将四个连接字符串的数据在资源文件中通过键值 对(key=value)的方式放置, 不要任何符号, 一条占一行

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_1129
jdbc.username=root
jdbc.password=123

properties: 引入外部的属性文件
resource: 从类路径下引入属性文件
url: 引入网络路径或者是磁盘路径下的属性文件

< properties resource=“db.properties” > < /properties>

3)在 environment 元素的 dataSource 元素中为其动态设置

在这里插入图片描述 settings 设置:改变 MyBatis 的运行时行为

<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods"
value="equals,clone,hashCode,toString"/>
</settings>

4 typeAliases 别名处理
在这里插入图片描述在这里插入图片描述

MyBatis-映射文件Mapper.xml

在这里插入图片描述自动映射
开启自动驼峰命名规则映射功能, mapUnderscoreToCamelCase=true。

在这里插入图片描述

自定义resultMap
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述什么叫延迟加载?
什么时候使用什么时候加载。
延迟加载要解决什么问题呢?
内存的使用问题。使用延迟加载来提升查询的效率, 只需要在全局的Settings 中进行如下的配置:

<!-- 开启延迟加载 -->
	< setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置加载的数据是按需 -->
	< setting name="aggressiveLazyLoading" value="false"/>

3.对象延迟加载的应用场景?
当一个对象占用的内存比较大,而且使用频率比较少。
如:int array = new int[4096]
连接池对象是否适合延迟加载?
个人认为:不适合。
因为在需要使用的时候才去创建连接池,创建对象,分配内存等操作,性能慢,用户访问资源时慢,体验不好。

MyBatis 动态 SQL

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

<select id="getEmpsByConditionForeach"
resultType="com.atguigu.mybatis.beans.Employee">
	select id , last_name, email ,gender from tbl_employee where id in
<foreach collection="ids" item="curr_id" open="(" close=")"separator="," >
		#{curr_id}
	</foreach>
</select>

MyBatis 缓存机制

在这里插入图片描述

一级缓存

在这里插入图片描述

一级缓存演示&失效情况

在这里插入图片描述

二级缓存

在这里插入图片描述在这里插入图片描述

缓存有关设置

在这里插入图片描述

MyBatis-逆向工程

在这里插入图片描述

• 官方文档地址
http://www.mybatis.org/generator/
• 官方工程地址
https://github.com/mybatis/generator/releases

  1. 导入逆向工程的 jar 包
    mybatis-generator-core-1.3.2.jar
    在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD
MyBatis3: 生成带条件的CRUD
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_2020"
userId="root"
password="123">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.atguigu.mybatis.beans"
targetProject=".\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.atguigu.mybatis.dao"
targetProject=".\conf">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.mybatis.dao" targetProject=".\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<table tableName="tbl_dept" domainObjectName="Department"></table>
<table tableName="tbl_employee" domainObjectName="Employee"></table>
</context>
</generatorConfiguration>

在这里插入图片描述
在这里插入图片描述
逆向工程的使用

@Test
public void testSelect() throws Exception {
	SqlSessionFactory ssf = getSqlSessionFactory();
	SqlSession session = ssf.openSession();

try {
	EmployeeMapper mapper =
		session.getMapper(EmployeeMapper.class);
	List<Employee> emps = mapper.selectAll();
	for (Employee employee : emps) {
			System.out.println(employee);
	}
} finally {
	session.close();
	}
}


@Test
public void testSelect2() throws Exception {
	SqlSessionFactory ssf = getSqlSessionFactory();
	SqlSession session = ssf.openSession();
try {
	EmployeeMapper mapper =
	session.getMapper(EmployeeMapper.class);
	//条件查询: 名字中带有'张' 并且 email中'j' 或者 did = 2
	EmployeeExample example = new EmployeeExample();
	Criteria criteria = example.createCriteria();
	criteria.andLastNameLike("%张%");
	criteria.andEmailLike("%j%");
	//or
	Criteria criteriaOr = example.createCriteria();
	criteriaOr.andDIdEqualTo(2);
	example.or(criteriaOr);
	List<Employee> emps = mapper.selectByExample(example);
	for (Employee employee : emps) {
	System.out.println(employee);
	}
} finally {
	session.close();
	}
}


实践

mybatis-config.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>

    <plugins>
        <!-- PageHelper分页插件 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">

            <!-- 4.0.0 以上版本可自动识别 -->
            <property name="dialect" value="mysql"/>

            <!-- RowBounds:参数offset作为PageNum使用 - 默认不使用 -->
            <property name="offsetAsPageNum" value="false"/>

            <!-- RowBounds:是否进行count查询 - 默认不查询 -->
            <property name="rowBoundsWithCount" value="false"/>

            <!-- 当设置为true的时候,如果pagesize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果 -->
            <property name="pageSizeZero" value="true"/>

            <!-- 分页合理化 -->
            <property name="reasonable" value="false"/>

            <!-- 是否支持接口参数来传递分页参数,默认false -->
            <property name="supportMethodsArguments" value="false"/>

            <!-- 是否返回分页信息 -->
            <property name="returnPageInfo" value="none"/>
        </plugin>
    </plugins>

</configuration>

UserMapper.xml

<?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 namespace="com.xxx.dao.UserMapper">

  <!--开启二级缓存,使用Ehcache缓存框架-->
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

    <!--user的映射结果集-->
    <resultMap type="com.xxx.entity.User" id="UserMap">
    //column(数据表属性) jdbcType(表属性的类型)property(实体类属性) 
        <result property="userId" column="user_id" jdbcType="OTHER"/>
        <result property="userName" column="user_name" jdbcType="VARCHAR"/>
        <result property="registerTime" column="register_time" jdbcType="TIMESTAMP"/>
        <result property="imagePath" column="image_path" jdbcType="VARCHAR"/>
    </resultMap>

    <!--全部字段-->
    <sql id="allColumn"> user_id,user_name, register_time, image_path </sql>
    
    <!--通用对User各个属性的值的非空判断-->
    <sql id="commonsValue">
       
        <if test="userName != null and userName != ''">
                user_name = #{userName},
        </if>
        <if test="registerTime != null">
                register_time = #{registerTime},
        </if>
        <if test="imagePath != null and imagePath != ''">
                image_path = #{imagePath},
        </if>
    </sql>
    
    <!--新增user:哪个字段不为空就添加哪列数据,返回自增主键-->
    <insert id="insert" keyProperty="userId" useGeneratedKeys="true">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
  <if test="userName != null and userName != ''">
                user_name,
        </if>
        <if test="registerTime != null">
                register_time,
        </if>
        <if test="imagePath != null and imagePath != ''">
                image_path,
        </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
        <if test="userName != null and userName != ''">
                #{userName},
        </if>
        <if test="registerTime != null">
                #{registerTime},
        </if>
        <if test="imagePath != null and imagePath != ''">
                #{imagePath},
        </if>
        </trim>
    </insert>
   
    <!--删除user:通过主键-->
    <delete id="deleteById">
        delete from user
        <where>
            user_id = #{userId}
        </where>
    </delete>
    
    <!--查询单个user-->
    <select id="queryById" resultMap="UserMap">
        select
        <include refid="allColumn"></include>
        from user
        <where>
            user_id = #{userId}
        </where>
    </select>

    <!--查询单个user-->
    <select id="getUserByOpenId" resultMap="UserMap">
        select
        <include refid="allColumn"></include>
        from user
        <where>
            open_id = #{openId}
        </where>
    </select>

    <!--查询所有user-->
    <select id="queryAllByLimit" resultMap="UserMap">
        select
        <include refid="allColumn"></include>
        from user
    </select>

    <!--通过实体作为筛选条件查询-->
    <select id="queryAll" resultMap="UserMap">
        select
          <include refid="allColumn"></include>
        from user
        <trim prefix="where" prefixOverrides="and" suffixOverrides=",">
            <include refid="commonsValue"></include>
        </trim>
    </select>

    <!--通过主键修改数据-->
    <update id="update">
        update user
        <set>
            <include refid="commonsValue"></include>
        </set>
        <where>
            user_id = #{userId}
        </where>
    </update>

</mapper>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值