一、概述

1.1 JDBC

  • MyBatis是一个Java持久层框架,Java中操作关系型 数据库用的是JDBC,MyBatis是对JDBC的一个封装。

1.2 JDBC编程中问题

  • 企业开发中,根据项目大小、特点进行技术选型 ,JDBC操作数据库时效率是很高的,jdbc也是技术选型的参考。

  • 1、数据库连接频繁的创建和关闭,缺点浪费数据库的资源,影响操作效率。设想:使用数据库连接池

  • 2、sql语句是硬编码,如果需求变更需要修改sql,就需要修改java代码,需要重新编译,系统不易维护。设想:将sql语句 统一配置在文件中,修改sql不需要修改java代码。

  • 3、通过preparedStatement向占位符设置参数,存在硬编码( 参数位置,参数)问题。系统不易维护。设想:将sql中的占位符及对应的参数类型配置在配置文件中,能够自动输入映射。

  • 4、遍历查询结果集存在硬编码(列名)。设想:自动进行sql查询结果向java对象的映射(输出映射)。

1.3 MyBatis介绍

  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatisibatis进行一些改进。 目前mybatisgithub上托管。git(分布式版本控制,当前比较流程)
  • MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
  • Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

1.4 Mybatis架构

二、MyBatis入门程序

2.1 需求

  • 实现用户查询:

    • 根据用户id(主键)查询用户信息(单条记录)
    • 根据用户名称模糊查询用户信息(多条记录)
  • 用户添加
  • 用户删除
  • 用户修改

2.2 引入MyBatis依赖

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis  继承了日志等依赖,默认为log4j-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>

2.3 配置 log4j.properties

# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

2.4 配置 SqlMapConfig.xml(公用文件)

  • 通过SqlMapConfig.xml加载mybatis运行环境。
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <!-- 属性定义
加载一个properties文件
在 properties标签 中配置属性值
-->
<properties resource="db.properties">
<!-- <property name="" value=""/> -->
</properties> <!-- 定义 别名 -->
<typeAliases>
<typeAlias type="com.hao.mybatis.po.User" alias="user"/>
</typeAliases> <!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<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> <!--加载mapper映射
如果将和spring整合后,可以使用整合包中提供的mapper扫描器,此处的mappers不用配置了。
-->
<mappers>
<!-- 通过resource引用mapper的映射文件 -->
<mapper resource="sqlmap/User.xml" /> </mappers>
</configuration>

2.5 根据id查询用户

pojo(User.java)

public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址 //getter & setter 省略
}

配置映射文件

  • 建议命名规则:表名+mapper.xml
  • 早期ibatis命名规则:表名.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">
<!-- namespace命名空间,为了对sql语句进行隔离,方便管理 ,mapper开发dao方式,使用namespace有特殊作用
mapper代理开发时将namespace指定为mapper接口的全限定名
-->
<mapper namespace="test">
<!-- 在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象
mapper.xml以statement为单位管理sql语句
--> <!-- 根据id查询用户信息 -->
<!--
id:唯一标识 一个statement
#{}:表示 一个占位符,如果#{}中传入简单类型的参数,#{}中的名称随意
parameterType:输入 参数的类型,通过#{}接收parameterType输入 的参数
resultType:输出结果 类型,不管返回是多条还是单条,指定单条记录映射的pojo类型
-->
<select id="findUserById" parameterType="int" resultType="com.hao.mybatis.po.User">
SELECT * FROM USER WHERE id= #{id} </select> </mapper>

编写Dao层

public interface UserDao {

    //根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据用户名称模糊查询用户列表
public List<User> findUserByUsername(String username) throws Exception;
//插入用户
public void insertUser(User user) throws Exception; }
public class UserDaoImpl implements UserDao {

    private SqlSessionFactory sqlSessionFactory;

    // 将SqlSessionFactory注入
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
} @Override
public User findUserById(int id) throws Exception { // 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(); // 根据id查询用户信息
User user = sqlSession.selectOne("test.findUserById", id); sqlSession.close(); return user; } @Override
public List<User> findUserByUsername(String username) throws Exception {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("test.findUserByName", username);
sqlSession.close();
return list;
} @Override
public void insertUser(User user) throws Exception {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close(); } }

测试

public class UserDaoImplTest {

    // 会话工厂
private SqlSessionFactory sqlSessionFactory; // 创建工厂
@Before
public void init() throws IOException { // 配置文件(SqlMapConfig.xml)
String resource = "SqlMapConfig.xml"; // 加载配置文件到输入 流
InputStream inputStream = Resources.getResourceAsStream(resource); // 创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test
public void testFindUserById() throws Exception { UserDao userDao = new UserDaoImpl(sqlSessionFactory); User user = userDao.findUserById(1);
System.out.println(user); } }

2.6 根据用户名称模糊查询用户信息

  • 根据用户名称模糊查询用户信息可能返回多条记录。

修改映射文件

<!-- 根据用户名称查询用户信息,可能返回多条
${}:表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.hao.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
  • 使用${}接收参数,此种方式相当于拼接 ,不能防止SQL注入

测试


@Test
public void testFindUserByName() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库
// 第一个参数:statement的位置,等于namespace+statement的id
// 第二个参数:传入的参数
List<User> list = null;
try {
list = sqlSession.selectList("test.findUserByName", "%小明%");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
} System.out.println(list.get(0).getUsername()); }

2.7 MyBatis开发过程小结

  • 1、编写SqlMapConfig.xml
  • 2、编写mapper.xml,定义了statement
  • 3、编程通过配置文件创建SqlSessionFactory
  • 4、通过SqlSessionFactory获取SqlSession
  • 5、通过。操作数据库,如果执行添加、更新、删除需要调用SqlSession.commit()
  • 6、SqlSesion使用完成要关闭

2.8 用户添加

  • 向用户表插入一条记录。

修改映射文件

<!-- 添加用户
parameterType:输入 参数的类型,User对象 包括 username,birthday,sex,address
#{}接收pojo数据,可以使用OGNL解析出pojo的属性值
#{username}表示从parameterType中获取pojo的属性值
-->
<insert id="insertUser" parameterType="com.hao.mybatis.po.User">
INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>

测试

@Test
public void testInsertUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库
// 创建插入数据对象
User user = new User();
user.setUsername("浪子燕青");
user.setAddress("河南郑州");
user.setBirthday(new Date());
user.setSex("1"); try {
sqlSession.insert("test.insertUser", user);
// 需要提交事务
sqlSession.commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
}
System.out.println("用户的id=" + user.getId()); } // 测试根据id删除用户(得到单条记录)
@Test
public void testDeleteUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库
try {
sqlSession.delete("test.deleteUser", 35);
// 需要提交事务
sqlSession.commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
} }

主键返回

  • 需求:user对象插入到数据库后,新记录的主键要通过user对象返回,通过user获取主键值。
  • 解决思路:
  • 通过LAST_INSERT_ID()获取刚插入记录的自增主键值,在insert语句执行后,执行select LAST_INSERT_ID()就可以获取自增主键。
<!--

order:设置selectKey中sql执行的顺序,相对于insert语句来说
keyProperty:将主键值设置到哪个属性
resultType:select LAST_INSERT_ID()的结果 类型
-->
<insert id="insertUser" parameterType="com.hao.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey> INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
  • 使用mysql的uuid机制生成主键
  • 使用uuid生成主键的好处是不考虑数据库移植后主键冲突问题。
    • 实现思路:先查询uuid得到主键,将主键设置到user对象中,将user对象插入数据库。
<insert id="insertUser" parameterType="com.hao.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="string">
select uuid()
</selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
  • 实现 oracle数据库主键返回,如何做??
  • oracle没有自增主键机制,使用序列完成主键生成。
  • 实现思路:
  • 先查询序列得到主键,将主键设置到user对象中,将user对象插入数据库。
<insert id="insertUser" parameterType="com.hao.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select 序列.nextval() from dual
</selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

2.9 用户删除和更新

修改映射文件

<!-- 用户删除  -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<!-- 用户更新
要求:传入的user对象中包括 id属性值
-->
<update id="updateUser" parameterType="com.hao.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>

测试

// 测试根据id删除用户(得到单条记录)
@Test
public void testDeleteUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库
try {
sqlSession.delete("test.deleteUser", 35);
// 需要提交事务
sqlSession.commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
} } // 测试根据id更新用户(得到单条记录)
@Test
public void testUpdateUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库
// 创建更新数据对象,要求必须包括 id
User user = new User();
user.setId(35);
user.setUsername("燕青");
user.setAddress("河南郑州");
// user.setBirthday(new Date());
user.setSex("1"); try {
sqlSession.update("test.updateUser", user);
// 需要提交事务
sqlSession.commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
} System.out.println("用户的id=" + user.getId()); }

三、Mybatis 与JDBC

  • 1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

    • 解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
  • 2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
    • 解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
  • 3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    • 解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
  • 4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
    • 解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

四、Mybatis与Hibernate

  • 企业开发进行技术选型 ,考虑mybatis与hibernate适用场景。
  • mybatis:入门简单,程序容易上手开发,节省开发成本 。mybatis需要程序员自己编写sql语句,是一个不完全 的ORM框架,对sql修改和优化非常容易实现 。
  • mybatis适合开发需求变更频繁的系统,比如:互联网项目。
  • hibernate:入门门槛高,如果用hibernate写出高性能的程序不容易实现。hibernate不用写sql语句,是一个 ORM框架。
  • hibernate适合需求固定,对象数据模型稳定,中小型项目,比如:企业OA系统。
  • 总之,企业在技术选型时根据项目实际情况,以降低成本和提高系统 可维护性为出发点进行技术选型。

五、配置文件

5.1 SqlMapConfig.xml

  • 是Mybatis全局配置文件,只有一个,名称不固定的

5.2 Mapper.xml

  • mapper.xml是以statement为单位进行配置。(把一个sql称为一个statement),satatement中配置 sql语句、parameterType输入参数类型(完成输入映射)、resultType输出结果类型(完成输出映射)。
  • 还提供了parameterMap配置输入参数类型(过期了,不推荐使用了)
  • 还提供resultMap配置输出结果类型(完成输出映射)

5.3 #{}

  • 表示一个占位符,向占位符输入参数,mybatis自动进行java类型和jdbc类型的转换。
  • 程序员不需要考虑参数的类型,比如:传入字符串,mybatis最终拼接好的sql就是参数两边加单引号。
  • #{}接收pojo数据,可以使用OGNL解析出pojo的属性值

5.4 ${}

  • 表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。
  • ${}也可以接收pojo数据,可以使用OGNL解析出pojo的属性值
  • 缺点:不能防止sql注入。

六、Mybatis 重要 API

6.1 SqlSession

6.2 SqlSessionFactoryBuilder

  • SqlSessionFactoryBuilder是以工具类方式来使用,需要创建sqlSessionFactory就new一个SqlSessionFactoryBuilder。

6.3 sqlSessionFactory

  • 正常开发时,以单例方式管理sqlSessionFactory,整个系统运行过程中sqlSessionFactory只有一个实例,将来和spring整合后由spring以单例方式管理sqlSessionFactory。

6.4 SqlSession

  • sqlSession是一个面向用户(程序员)的接口,程序员调用sqlSession的接口方法进行操作数据库。
  • sqlSession能否以单例 方式使用??
    • 由于sqlSession是线程不安全,所以sqlSession最佳应用范围在方法体内,在方法体内定义局部变量使用sqlSession。

七、Mapper代理的方式

7.1 简介

  • 原始dao开发方式,程序员需要写dao接口和dao 的实现类

    • dao的实现类中存在重复代码,整个mybatis操作的过程代码模板重复(先创建sqlsession、调用sqlsession的方法、关闭sqlsession)
    • dao的实现 类中存在硬编码,调用sqlsession方法时将statement的id硬编码。
  • mapper代理的方式,程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象。本身dao在三层架构中就是一个通用的接口。

7.2 mapper开发规范

  • 要想让mybatis自动创建dao接口实现类的代理对象,必须遵循一些规则:

  • 1、mapper.xml中namespace指定为mapper接口的全限定名

<?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命名空间,为了对sql语句进行隔离,方便管理 ,mapper开发dao方式,使用namespace有特殊作用
mapper代理开发时将namespace指定为mapper接口的全限定名
-->
<mapper namespace="com.hao.mybatis.mapper.UserMapper">
<!-- 在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象
mapper.xml以statement为单位管理sql语句
-->
  • 此步骤目的:通过mapper.xml和mapper.java进行关联。

  • 2、mapper.xml中statement的id就是mapper.java中方法名

  • 3、mapper.xml中statement的parameterType和mapper.java中方法输入参数类型一致

  • 4、mapper.xml中statement的resultType和mapper.java中方法返回值类型一致.

  • 5、mapper映射文件的命名方式建议:表名Mapper.xml

<!-- 根据id查询用户信息 -->
<!--
id:唯一标识 一个statement
#{}:表示 一个占位符,如果#{}中传入简单类型的参数,#{}中的名称随意
parameterType:输入 参数的类型,通过#{}接收parameterType输入 的参数
resultType:输出结果 类型,不管返回是多条还是单条,指定单条记录映射的pojo类型
-->
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id= #{id} </select>

7.3 mapper接口

  • mybatis提出了mapper接口,相当 于dao 接口。
  • mapper接口的命名方式建议:表名Mapper
public interface UserMapper {
//根据用户id查询用户信息
public User findUserById(int id) throws Exception;
}

7.4 在SqlMapConfig.xml中加载

<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>

7.5 返回单个对象和集合对象

  • 不管查询记录是单条还是多条,在statement中resultType定义一致,都是单条记录映射的pojo类型。
  • mapper接口方法返回值,如果是返回的单个对象,返回值类型是pojo类型,生成的代理对象内部通过selectOne获取记录,如果返回值类型是集合对象,生成的代理对象内部通过selectList获取记录。
//根据用户id查询用户信息
public User findUserById(int id) throws Exception; //根据用户名称 查询用户信息
public List<User> findUserByName(String username) throws Exception;

7.6 问题

返回值的问题

  • 如果方法调用的statement,返回是多条记录,而mapper.java方法的返回值为pojo,此时代理对象通过selectOne调用,由于返回多条记录,所以报错:
    org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

输入参数的问题

  • 使用mapper代理的方式开发,mapper接口方法输入参数只有一个,可扩展性是否很差
  • 可扩展性没有问题,因为dao层就是通用的,可以通过扩展pojo(定义pojo包装类型)将不同的参数(可以是pojo也可以简单类型)传入进去。

八、sqlMapConfig.xml 配置文件

  • SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

8.1 properties属性定义

  • 可以把一些通用的属性值配置在属性文件中,加载到mybatis运行环境内。
  • 比如:创建db.properties配置数据库连接参数。

<!-- 属性定义
加载一个properties文件
在 properties标签 中配置属性值
-->
<properties resource="db.properties">
<!-- <property name="" value=""/> -->
</properties>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<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>
  • 注意 MyBatis 将按照下面的顺序来加载属性:
  • 在 properties 元素体内定义的属性首先被读取。
  • 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
  • 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。
  • 建议使用properties,不要在properties中定义属性,只引用定义的properties文件中属性,并且properties文件中定义的key要有一些特殊的规则。

8.2 settings全局参数配置

  • mybatis运行时可以调整一些全局参数(相当于软件的运行参数)
  • 根据使用需求进行参数配置。
  • 注意:小心配置,配置参数会影响mybatis的执行。
  • ibatis的全局配置参数中包括很多的性能参数(最大线程数,最大待时间。。。),通过调整这些性能参数使ibatis达到高性能的运行,mybatis没有这些性能参数,由mybatis自动调节。

8.3 typeAliases(常用)

  • 可以将parameterType、resultType中指定的类型 通过别名引用。

8.4 mybaits提供了很多别名

别名  映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal

8.5 自定义别名

  • 可以单个定义也可以批量定义
<!-- 定义 别名 -->
<typeAliases>
<!--
单个别名的定义
alias:别名,type:别名映射的类型 -->
<!-- <typeAlias type="com.hao.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
指定包路径,自动扫描包下边的pojo,定义别名,别名默认为类名(首字母小写或大写)
-->
<package name="com.hao.mybatis.po"/> </typeAliases>

8.6 使用别名

  • 在parameterType、resultType中使用别名:
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id= #{id}
</select>

8.7 typeHandlers

  • 类型处理器将java类型和jdbc类型进行映射。
  • mybatis默认提供很多类型处理器,一般情况下够用了。

8.8 mappers

<!--加载mapper映射
如果将和spring整合后,可以使用整合包中提供的mapper扫描器,此处的mappers不用配置了。
-->
<mappers>
<!-- 通过resource引用mapper的映射文件 -->
<mapper resource="sqlmap/User.xml" />
<!-- <mapper resource="mapper/UserMapper.xml" /> 此处代码中已经删除掉了,移到了mapper.java 同目录下-->
<!-- 通过class引用mapper接口
class:配置mapper接口全限定名
要求:需要mapper.xml和mapper.java同名并且在一个目录 中
-->
<!-- <mapper class="com.hao.mybatis.mapper.UserMapper"/> -->
<!-- 批量mapper配置
通过package进行自动扫描包下边的mapper接口,
要求:需要mapper.xml和mapper.java同名并且在一个目录 中 -->
<package name="com.hao.mybatis.mapper"/> </mappers>

8.9 输入和输出映射

  • 通过parameterType完成输入映射,通过resultType和resultMap完成输出映射。

九、resultMap

9.1 简介

  • resultType:指定输出结果的类型(pojo、简单类型、hashmap..),将sql查询结果映射为java对象,使用resultType注意:sql查询的列名要和resultType指定pojo的属性名相同,指定相同 属性方可映射成功,如果sql查询的列名要和resultType指定pojo的属性名全部不相同,list中无法创建pojo对象的。
  • resultMap:将sql查询结果映射为java对象。如果sql查询列名和最终要映射的pojo的属性名不一致,使用resultMap将列名和pojo的属性名做一个对应关系 (列名和属性名映射配置)

9.2 resultMap配置

<!-- 定义resultMap,列名和属性名映射配置
id:mapper.xml中的唯一标识
type:最终要映射的pojo类型
-->
<resultMap id="userListResultMap" type="user" >
<!-- 列名
id_,username_,birthday_
id:要映射结果集的唯 一标识 ,称为主键
column:结果集的列名
property:type指定的哪个属性中
-->
<id column="id_" property="id"/>
<!-- result就是普通列的映射配置 -->
<result column="username_" property="username"/>
<result column="birthday_" property="birthday"/>
</resultMap>

9.3 resultMap

<!-- 使用resultMap作结果映射
resultMap:如果引用resultMap的位置和resultMap的定义在同一个mapper.xml,
直接使用resultMap的id,如果不在同一个mapper.xml要在resultMap的id前边加namespace -->
<select id="findUserListResultMap" parameterType="userQueryVo" resultMap="userListResultMap"> select id id_,username username_,birthday birthday_ from user where username like '%${userCustom.username}%'
</select>

9.4 mapper.java

//查询用户,使用resultMap进行映射
public List<User> findUserListResultMap(UserQueryVo userQueryVo)throws Exception;

十、动态sql

  • mybatis重点是对sql的灵活解析和处理。

10.1 需求

  • 将自定义查询条件查询用户列表和查询用户列表总记录数改为动态sql

10.2 if和where

    <!-- where标签相当 于where关键字,可以自动去除第一个and -->
<where>
<if test="userCustom!=null">
....
</if> </where>

10.3 sql片段

  • 通过sql片段可以将通用的sql语句抽取出来,单独定义,在其它的statement中可以引用sql片段。
  • 通用的sql语句,常用:where条件、查询列

10.4 sql片段的定义

<!-- 将用户查询条件定义为sql片段
建议对单表的查询条件单独抽取sql片段,提高公用性
注意:不要将where标签放在sql片段
-->
<sql id="query_user_where">
<!-- 如果 userQueryVo中传入查询条件,再进行sql拼接-->
<!-- test中userCustom.username表示从userQueryVo读取属性值-->
<if test="userCustom!=null">
<if test="userCustom.username!=null and userCustom.username!=''">
and username like '%${userCustom.username}%'
</if>
<if test="userCustom.sex!=null and userCustom.sex!=''">
and sex = #{userCustom.sex}
</if>
<!-- 根据id集合查询用户信息 -->
<!-- 最终拼接的效果:
SELECT id ,username ,birthday FROM USER WHERE username LIKE '%小明%' AND id IN (16,22,25)
collection:集合的属性
open:开始循环拼接的串
close:结束循环拼接的串
item:每次循环取到的对象
separator:每两次循环中间拼接的串
-->
<foreach collection="ids" open=" AND id IN ( " close=")" item="id" separator=",">
#{id}
</foreach>
<!--
SELECT id ,username ,birthday FROM USER WHERE username LIKE '%小明%' AND (id = 16 OR id = 22 OR id = 25)
<foreach collection="ids" open=" AND ( " close=")" item="id" separator="OR">
id = #{id}
</foreach>
-->
<!-- 还有很的查询条件 -->
</if>
</sql>

10.5 引用sql片段

<!-- where标签相当 于where关键字,可以自动去除第一个and -->
<where>
<!-- 引用sql片段,如果sql片段和引用处不在同一个mapper必须前边加namespace -->
<include refid="query_user_where"></include>
<!-- 下边还有很其它的条件 -->
<!-- <include refid="其它的sql片段"></include> -->
</where>

10.6 foreach

  • 在statement通过foreach遍历parameterType中的集合类型。

【Mybatis】 入门的更多相关文章

  1. MyBatis1:MyBatis入门

    MyBatis是什么 MyBatis是什么,MyBatis的jar包中有它的官方文档,文档是这么描述MyBatis的: MyBatis is a first class persistence fra ...

  2. mybatis入门基础(二)----原始dao的开发和mapper代理开发

    承接上一篇 mybatis入门基础(一) 看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先 ...

  3. MyBatis入门基础(一)

    一:对原生态JDBC问题的总结 新项目要使用mybatis作为持久层框架,由于本人之前一直使用的Hibernate,对mybatis的用法实在欠缺,最近几天计划把mybatis学习一哈,特将学习笔记记 ...

  4. MyBatis入门案例、增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  5. mybatis入门_mybatis基本原理以及入门程序

    一.传统jdbc存在的问题 1.创建数据库的连接存在大量的硬编码, 2.执行statement时存在硬编码. 3.频繁的开启和关闭数据库连接,会严重影响数据库的性能,浪费数据库的资源. 4.存在大量的 ...

  6. MyBatis入门学习教程-使用MyBatis对表执行CRUD操作

    上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...

  7. MyBatis入门学习(二)

    在MyBatis入门学习(一)中我们完成了对MyBatis简要的介绍以及简单的入门小项目测试,主要完成对一个用户信息的查询.这一节我们主要来简要的介绍MyBatis框架的增删改查操作,加深对该框架的了 ...

  8. MyBatis入门学习(一)

    一.MyBatis入门简要介绍(百科) MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyB ...

  9. MyBatis入门案例 增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  10. MyBatis入门(五)---延时加载、缓存

    一.创建数据库 1.1.建立数据库 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.7.9-log : Database - mybatis ****** ...

随机推荐

  1. LINUX 安装 VMware-Tools(附常见问题)

    mkdir /cdrom #创建光驱挂载目录 mount /dev/cdrom /cdrom # 加载光驱 tar -zxvf /cdro/VMwareTools**********.tar.gz ~ ...

  2. JavaScript获取手机屏幕翻转方法

    /*屏幕翻转*/ window.addEventListener(window['onorientationchange'] ? 'orientationchange' : 'resize', fun ...

  3. mysql日期加一个天数获得新的日期

    原文地址:https://476057266-qq-com.iteye.com/blog/2047671 在当前的日期上加三天,天数随便改: SELECT date_add(CURRENT_DATE( ...

  4. C++标准模板库集合类与映射类总结

    一.STL集合类 标准模板库向程序员提供了一些容器类,以便在应用程序中频繁而快速的搜索.std::set和std::multiset用于存储一组经过排序的元素,其查找元素的复杂度为对数,而unorde ...

  5. C++STL位标志、智能指针与异常处理

    参考<21天学通C++>第25章节,对STL位标志进行介绍.就是当需要不是像char int long 等整个字节数的数据表示形式,而是使用二进制位表示的时候,通常使用这里讲到的位标志.从 ...

  6. dockerui 安装

    meiya@meiya:~$ docker pull abh1nav/dockerui Using default tag: latest latest: Pulling from abh1nav/d ...

  7. pycharm 提示:this license **** has been cancelled(2)

    pycharm安装激活过程中,提示 this license **** has been cancelled .这个问题并不是你的激活码不对,而是需要修改系统的hosts文件,下面详细讲解下如何修改h ...

  8. 虚拟机中windows下制作超级隐藏账户

    这篇博客非原创,我只是将很多大佬写的东西理解了一下写了出来. 接下来的实验最好在虚拟机进行,因为可以快照~ 制作隐藏用户可以说是两种方法但是基本操作一样,所以我们穿插着进行一种是隐藏账户,一种是影子账 ...

  9. Beginning Linux Programming 学习--chapter 17 Programming KDE using QT

    KDE: KDE,K桌面环境(K Desktop Environment)的缩写.一种著名的运行于 Linux.Unix 以及FreeBSD 等操作系统上的自由图形桌面环境,整个系统采用的都是 Tro ...

  10. LeetCode 643. 子数组最大平均数 I(Maximum Average Subarray I)

    643. 子数组最大平均数 I 643. Maximum Average Subarray I 题目描述 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. LeetCo ...