天天看点

MybatisMybatisMyBatis-逆向工程

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的接口绑定是什么?有哪些实现方式?
MybatisMybatisMyBatis-逆向工程

文章目录

    • JDBC
  • Mybatis
    • HelloWorld
      • 通过Mapper 接口开发 MyBatis HelloWorld
    • MyBatis 全局配置文件
    • MyBatis-映射文件Mapper.xml
    • MyBatis 动态 SQL
    • MyBatis 缓存机制
        • 一级缓存
        • 一级缓存演示&失效情况
        • 二级缓存
          • 缓存有关设置
  • MyBatis-逆向工程
    • 实践
      • mybatis-config.xml
      • UserMapper.xml

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

MybatisMybatisMyBatis-逆向工程

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的时候有提示

MybatisMybatisMyBatis-逆向工程

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 元素中为其动态设置

MybatisMybatisMyBatis-逆向工程

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 别名处理

MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程

MyBatis-映射文件Mapper.xml

MybatisMybatisMyBatis-逆向工程

自动映射

开启自动驼峰命名规则映射功能, mapUnderscoreToCamelCase=true。

MybatisMybatisMyBatis-逆向工程

自定义resultMap

MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程

什么叫延迟加载?

什么时候使用什么时候加载。

延迟加载要解决什么问题呢?

内存的使用问题。使用延迟加载来提升查询的效率, 只需要在全局的Settings 中进行如下的配置:

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

3.对象延迟加载的应用场景?

当一个对象占用的内存比较大,而且使用频率比较少。

如:int array = new int[4096]

连接池对象是否适合延迟加载?

个人认为:不适合。

因为在需要使用的时候才去创建连接池,创建对象,分配内存等操作,性能慢,用户访问资源时慢,体验不好。

MyBatis 动态 SQL

MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
<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 缓存机制

MybatisMybatisMyBatis-逆向工程

一级缓存

MybatisMybatisMyBatis-逆向工程

一级缓存演示&失效情况

MybatisMybatisMyBatis-逆向工程

二级缓存

MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
缓存有关设置
MybatisMybatisMyBatis-逆向工程

MyBatis-逆向工程

MybatisMybatisMyBatis-逆向工程

• 官方文档地址

http://www.mybatis.org/generator/

• 官方工程地址

https://github.com/mybatis/generator/releases

  1. 导入逆向工程的 jar 包

    mybatis-generator-core-1.3.2.jar

    MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程
<?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>
           
MybatisMybatisMyBatis-逆向工程
MybatisMybatisMyBatis-逆向工程

逆向工程的使用

@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>
           

继续阅读