MyBatis学习笔记

一、MyBatis 简介

【官方介绍】

       MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

 

       MyBatis 主要是一个持久层框架,负责与数据库进行交互。同样功能的常用框架是 Hibernate,其中 Hibernate 是一个全自动的持久层框架,也就是不再需要我们手动写 SQL 语句了。MyBatis 是一个半自动的持久层框架,在书写映射文件的时候,还需要我们手动添加一些 SQL 语句。后面,为了优化这个操作,我们会采用“逆向工程工具”来自动生成常用的操作方法,就可以免掉手写 SQL 的痛苦。

 

       MyBatis 属于 Apache 基金组织旗下的一个开源框架,以前叫 iBatis,面试的时候千万别忘了。MyBatis 的使用其实非常简单,只需要一个接口类和一个映射文件即可。只要在数据库中有同样名字的数据表,它们就会自动匹配映射,然后进行交互。查出来的数据可以封装到 JavaBean 中。

 

       官网:http://www.mybatis.org/mybatis-3/zh/index.html 中文文档

       下载:https://github.com/mybatis/mybatis-3/releases

       Maven 构建:

<dependency>

  <groupId>org.mybatis</groupId>

  <artifactId>mybatis</artifactId>

  <version>x.x.x</version>

</dependency>

 

 

 

 

 

二、MyBatis 的运行原理

 

 

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

 

也就是,我们如果想要跟数据库打交道的话,必须要有个 sqlSession 会话对象,这个对象只能通过 SqlSessionFactory 生产出来。

 

一、输入输出映射

1. 输入映射

1)新建 QueryBean 类,添加 User 类型字段和 get\set 方法。

 

public class QueryBean implements Serializable {

      

       private User user;

 

       public User getUser() {

              return user;

       }

 

       public void setUser(User user) {

              this.user = user;

       }

}

 

2)编辑 UserMapper.xml配置文件。

 

       <!-- 根据 QueryBean 查找用户 -->

       <select id="findUserByQueryBean" parameterType="QueryBean" resultType="User">

              select * from user where username like '%${user.username}%' and sex = #{user.sex}

       </select>

 

3)编辑 UserMapper 接口类。

 

public List<User> findUserByQueryBean(QueryBean queryBean);

 

4)编辑 UserTest测试类

 

@Test

public void fun2() throws Exception{

             

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       // 创建 QueryBean 实例

       QueryBean queryBean = new QueryBean();

             

       // 创建 User 实例

       User user = new User();

       user.setUsername("肉");

       user.setSex("男");

             

       queryBean.setUser(user);

             

       List<User> userList = mapper.findUserByQueryBean(queryBean);

             

       for (User user2 : userList) {

              System.out.println(user2);

       }

}

2. 输出映射

1)编辑 UserMapper.xml 文件。

 

<select id="findUserCount" resultType="int">

       select count(*) from user;        

</select>

 

2)编辑 UserMapper 接口文件。

 

public Integer findUserCount();

 

3)编辑 UserTest 测试文件。

 

@Test

public void fun3() throws Exception{

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       System.out.println("总人数为:" + mapper.findUserCount() + " 人。");

}

 

 

 

 

二、动态 SQL 语句

1. if 标签

1)编辑 UserMapper.xml 配置文件。

 

<select id="findUserByUserNameAndSex" parameterType="User" resultType="User">

       select * from user where 1 = 1

 

       <if test="username != null and username != ''">

              and username like concat('%',#{username},'%')

       </if>

 

       <if test="sex != null and sex != ''">

              and sex = #{sex}

       </if>

</select>

 

2)编辑 UserMapper 接口类。

 

public List<User> findUserByUserNameAndSex(User user);

 

3)编辑 UserTest 测试类。

 

@Test

public void fun3() throws Exception{

             

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       User user = new User();

       user.setUsername("花");

       user.setSex("女");

             

       List<User> userList = mapper.findUserByUserNameAndSex(user);

 

       for (User user2 : userList) {

              System.out.println(user2);

       }

}

 

2. where 标签

1)编辑 UserMapper.xml 文件

 

       <select id="findUserByUserNameAndSex2" parameterType="User"

              resultType="User">

 

              select * from user

 

              <where>

                     <if test="username != null and username != ''">

                            and username like concat('%',#{username},'%')

                     </if>

 

                     <if test="sex != null and sex != ''">

                            and sex = #{sex}

                     </if>

              </where>

 

       </select>

3. sql 标签

1)编辑 UserMapper.xml 文件,抽取常用的语句。

 

       <!-- 抽取常用的条件语句 -->

       <sql id="where_sql">

              <where>

                     <if test="username != null and username != ''">

                            and username like concat('%',#{username},'%')

                     </if>

 

                     <if test="sex != null and sex != ''">

                            and sex = #{sex}

                     </if>

              </where>

       </sql>

 

2)引用常用语句。

 

<!-- 引入常用的语句 -->

<include refid="where_sql"/>

 

4. foreach 标签

1)编辑 QueryBean 类,添加 ids 集合。

 

private List<Integer> ids;

      

public List<Integer> getIds() {

       return ids;

}

 

public void setIds(List<Integer> ids) {

       this.ids = ids;

}

 

2)编辑 UserMapper.xml 配置文件。

 

<!-- 使用 foreach 循环 -->

<select id="findUserByIds" parameterType="QueryBean" resultType="User">

      

       select * from user

             

       <where>

              <if test="ids != null">

                     <!-- 把传入的 ids 进行遍历,根据单个 id 值查找对应的用户信息

                            collection 指的是我们需要操作的集合

                            item 指的是集合中泛型的变量名

                            open 指的是条件从哪里开始

                            close 指的是条件从哪里结束

                            separator 指的是元素中间的逗号

                            SELECT * FROM USER WHERE id IN (1,2,3,6,7,8)

                     -->

                     <foreach collection="ids" item="id" open="id IN (" close=")" separator=",">

                            #{id}

                     </foreach>

              </if>

       </where>     

</select>

 

3)编辑 UserMapper 接口类。

 

public List<User> findUserByIds(QueryBean qb);

 

4)编辑 UserTest 测试类。

@Test

public void fun4() throws Exception{

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       QueryBean qb = new QueryBean();

             

       List<Integer> ids = new ArrayList<>();

       ids.add(1);

       ids.add(2);

       ids.add(7);

       ids.add(8);

             

       qb.setIds(ids);

             

       List<User> userList = mapper.findUserByIds(qb);

             

       for (User user : userList) {

              System.out.println(user);

       }

}

 

 

 

三、对单个对象映射

1. 自动映射

1)新建 Order 类。

 

public class Orders implements Serializable {

 

       private Integer id;

       private Integer userId; // 下单用户id

       private String number; // 订单号

       private Date createtime; // 创建订单时间

       private String note; // 备注

 

       // 关联 User

       private User user;

 

       // get 和 set 方法

}

 

2)添加 UserOrder 类,充当中间表。

 

public class UserOrder extends Orders {

 

       private Integer uid;

       private String username;

       private String sex;

       private Date birthday;

       private String address;

 

       // get 和 set 方法
}

 

3)编辑 UserMapper.xml 配置文件。

 

<!-- 一对一映射:自动映射 -->

<select id="findOrdersAndUser" resultType="com.neuedu.pojo.UserOrder">

       SELECT o.*,

       u.`username`, u.`address`

       FROM orders o, USER u

       WHERE o.`user_id` =

       u.`id`;

</select>

4)编辑 UserMapper 接口类。

 

public List<UserOrder> findOrdersAndUser();

 

5)编辑 UserMapperTest 类。

 

@Test

public void fun() throws Exception{

             

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       List<Orders> oList = mapper.findOrdersAndUser();

      

       for (Orders order : oList) {

              System.out.println(order.getUser().getUsername());

       }

}

 

2. 手动映射

1)编辑 UserMapper.xml 配置文件,使用 <resultMap> 标签进行配置。

 

       <!-- 一对一映射:手动映射(了解) -->

       <resultMap type="com.neuedu.pojo.Orders" id="OrderAndUserResultMap">

              <id column="id" property="id" />

              <result column="user_id" property="userId" />

              <result column="number" property="number" />

              <result column="createtime" property="createtime" />

              <result column="note" property="note" />

 

              <!-- 关联 User -->

              <association property="user" javaType="User">

                     <id column="uid" property="id" />

                     <result column="username" property="username" />

                     <result column="sex" property="sex" />

                     <result column="birthday" property="birthday" />

                     <result column="address" property="address" />

              </association>

       </resultMap>

 

       <select id="findOrdersAndUser2" resultMap="OrderAndUserResultMap">

              SELECT o.*, u.id uid,

              u.`username`, u.`address`

              FROM orders o, USER u

              WHERE o.`user_id` =

              u.`id`;

       </select>

 

2)编辑 UserMapper 接口类。

 

public List<UserOrder> findOrdersAndUser2();

 

3)编辑 UserTest 测试类

 

@Test

public void fun() throws Exception{

             

       SqlSession session = factory.openSession();

       UserMapper mapper = session.getMapper(UserMapper.class);

             

       List<Orders> oList = mapper.findOrdersAndUser2();

      

       for (Orders order : oList) {

              System.out.println(order.getUser().getUsername());

       }

}

 

 

 

 

 

 

四、对集合对象映射

1. 编辑 User 类,添加 Orders 集合,一个用户可以拥有多个订单。

 

       // 一个用户,可以有多个订单,所有的订单都放在集合中

       private List<Orders> ordersList;

 

       public List<Orders> getOrdersList() {

              return ordersList;

       }

 

       public void setOrdersList(List<Orders> ordersList) {

              this.ordersList = ordersList;

       }

 

2. 编辑 UserMapper.xml 文件,添加映射配置。

 

       <!-- 一个用户,拥有多个订单 -->

       <resultMap type="User" id="UserAndOrdersResultMap">

              <!-- 先配置 User 的属性 -->

              <id column="id" property="id" />

              <result column="username" property="username" />

              <result column="birthday" property="birthday" />

              <result column="sex" property="sex" />

              <result column="address" property="address" />

 

              <!-- 再配置 Orders 集合 -->

              <collection property="ordersList" ofType="Orders">

                     <id column="oid" property="id" />

                     <result column="user_id" property="userId" />

                     <result column="number" property="number" />

                     <result column="createtime" property="createtime" />

              </collection>

       </resultMap>

 

       <select id="findUserAndOrders" resultMap="UserAndOrdersResultMap">

              SELECT u.*, o.`id` oid, o.`number`, o.`createtime`

              FROM USER u, orders o

              WHERE u.`id` = o.`user_id`;

       </select>

 

3)编辑 UserMapper 接口类。

 

public List<User> findUserAndOrders();

 

4)编辑 UserTest 测试类。

 

       @Test

       public void fun2() throws Exception{

             

              SqlSession session = factory.openSession();

              UserMapper mapper = session.getMapper(UserMapper.class);

             

              List<User> userList = mapper.findUserAndOrders();

             

              for (User user : userList) {

                     System.out.println(user);

              }

       }

 

 

 

 

 

 

 

 

五、Spring 整合 MyBatis 框架

1. 搭建环境需要准备的 jar 包文件

       1)Spring 的 jar 包。

       2)MyBatis 的 jar 包。

       3)mybatis-spring 整合包:mybatis-spring-1.2.2.jar。

       4)数据驱动包:mysql-connector-java-5.1.7-bin.jar。

       5)数据源:dbcp、c3p0、

       6)日志包:log4j,在使用的时候,需要加 logging 包和 log4j.properties。

2. 需要准备的配置文件

       1)Spring 的核心配置文件:beans.xml

       2)MyBatis 的核心配置文件:SqlMapConfig.xml

       3)数据连接信息:db.properties

       4)日志文件:log4j.properties

3. 配置 Spring 的beans.xml 核心配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"

       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

 

       <!-- 加载配置文件 -->

       <context:property-placeholder location="classpath:db.properties" />

       <!-- 数据库连接池 -->

       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

              destroy-method="close">

              <property name="driverClassName" value="${jdbc.driver}" />

              <property name="url" value="${jdbc.url}" />

              <property name="username" value="${jdbc.username}" />

              <property name="password" value="${jdbc.password}" />

              <property name="maxActive" value="10" />

              <property name="maxIdle" value="5" />

       </bean>

 

       <!-- 整合Sql会话工厂归spring管理 -->

       <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

              <!-- 指定mybatis核心配置文件 -->

              <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>

              <!-- 指定会话工厂使用的数据源 -->

              <property name="dataSource" ref="dataSource"></property>

       </bean>

 

       <!-- 配置原生Dao实现 注意:class必须指定Dao实现类的全路径名称 -->

       <bean id="userDao" class="com.neuedu.dao.UserDaoImpl">

              <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>

       </bean>

 

       <!-- Mapper接口代理实现 -->

       <!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> -->

       <!-- 配置mapper接口的全路径名称 -->

       <!-- <property name="mapperInterface"

              value="com.neuedu.mapper.UserMapper"></property> -->

       <!-- <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> -->

       <!-- </bean> -->

 

       <!-- 使用包扫描的方式批量引入Mapper 扫描后引用的时候可以使用类名,首字母小写. -->

       <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

              <!-- 指定要扫描的包的全路径名称,如果有多个包用英文状态下的逗号分隔 -->

              <property name="basePackage" value="com.neuedu.mapper"></property>

       </bean>

</beans>

4. 配置数据源信息 db.properties 文件

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/hello?characterEncoding=utf-8

jdbc.username=root

jdbc.password=1234

5. 配置 SqlMapConfig.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>

 

       <typeAliases>

              <!-- 使用包扫描的方式批量定义别名 定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写 -->

              <package name="com.neuedu.pojo" />

       </typeAliases>

 

       <mappers>

              <mapper resource="User.xml" />

 

              <!-- 使用class属性引入接口的全路径名称: 使用规则: 1. 接口的名称和映射文件名称除扩展名外要完全相同 2. 接口和映射文件要放在同一个目录下 -->

              <!-- <mapper class="com.neuedu.mapper.UserMapper"/> -->

 

             <!-- 使用包扫描的方式批量引入Mapper接口 使用规则: 1. 接口的名称和映射文件名称除扩展名外要完全相同 2. 接口和映射文件要放在同一个目录下 -->

              <!-- <package name="com.neuedu.mapper"/> -->

       </mappers>

</configuration>

6. 使用原生 Dao 实现方式来整合

1)新建 UserDao 接口类和 UserDaoImpl 实现类。

       需要继承 SqlSessionDaoSupport 类,因为我们可以直接通过它使用 SqlSession 对象。

       然后,父类中还有 sqlSessionFactory 属性,可以让我们设置关联自动实现。

 

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {

      

       // 会话

       // SqlSession 是一个线程不安全的,然后像这种线程不安全最好放在一个代码块使用

       // 比如一般情况下,建议直接在方法体中使用即可

       // private SqlSession session = this.getSqlSession();

 

       @Override

       public User findUserById(Integer id) {

              SqlSession session = this.getSqlSession();

              return session.selectOne("findUserById", id);

              // 因为我们现在的 session 已经交给 spring 管理了,是不能手动关闭的

              // 如果你关了之后,其他地方则不可用

              // session.close();

       }

 

       @Override

       public List<User> findUserByName(String username) {

              SqlSession session = this.getSqlSession();

              return session.selectList("findUserByName", username);

       }

}

 

2)将 UserDaoImpl 交给 Spring 管理。

 

       <!-- 配置原生Dao实现 注意:class必须指定Dao实现类的全路径名称 -->

       <bean id="userDao" class="com.neuedu.dao.impl.UserDaoImpl">

              <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>

       </bean>

 

3)添加 UserDaoTest 测试类。

public class UserDaoTest {

      

       private ApplicationContext context;

      

       @Before

       public void addConfig(){

             

              context = new ClassPathXmlApplicationContext("classpath:beans.xml");

       }

 

       @Test

       public void run() {

             

              UserDao userDao = (UserDao)context.getBean("userDao");

             

              User user = userDao.findUserById(10);

              System.out.println("---------------------" + user);

             

              List<User> userList = userDao.findUserByName("明");

             

              for (User user2 : userList) {

                     System.out.println(user2);

              }

       }

}

 

7. 使用 Mapper 映射文件实现

 

1)编辑 beans.xml 文件,设置包扫描方式。

 

<!-- 使用包扫描的方式批量引入Mapper 扫描后引用的时候可以使用类名,首字母小写. -->

       <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

              <!-- 指定要扫描的包的全路径名称,如果有多个包用英文状态下的逗号分隔 -->

              <property name="basePackage" value="com.neuedu.mapper"></property>

       </bean>

 

2)编辑 UserMapper.xml 文件。

 

<mapper namespace="com.neuedu.mapper.UserMapper">

       <select id="findUserByName" resultType="com.neuedu.pojo.User"

parameterType="java.lang.String">

              select * from user where username like '%${value}%'

       </select>

</mapper>

 

3)编辑 UserMapper 接口类。

 

public interface UserMapper {

       public List<User> findUserByName(String name);

}

 

4)编辑 UserDaoTest 测试类。

 

       @Test

       public void run2(){

             

              // 因为我们使用了包扫描方式

              // 所以可以根据类的名字(首字母小写)来加载对应的实例

              UserMapper mapper = (UserMapper) context.getBean("userMapper");

             

              List<User> list = mapper.findUserByName("明");

             

              for (User user : list) {

                     System.out.println(user);

              }

       }

 

posted @ 2018-08-20 11:16  一飞要上天  阅读(346)  评论(0编辑  收藏  举报