MyBatis

一,mybatis的概念

mybatis是apache组织的一个开源项目,最初叫iBatis,2010年迁移到了Google改名为mybatis。2013年迁移GitHub。

mybatis是一个持久层框架,支持自定义动态sql,存储过程、高级映射。

mybatis对原有的jdbc中的所有操作都实现了封装,消除了所有jdbc的代码,使开发者只需要关心sql语句。

二,下载

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

三,搭建mybatis环境

  1. 在pom.xml中引入mybatis的依赖

    <dependencies>
        <!-- mybatis的依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <!-- mysql驱动包的依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
    </dependencies>

    建议使用日志,

    1. 引入日志的依赖

     <!-- 日志的依赖 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    1. 在resource目录下创建log4j.properties文件

    ### 设置###
    log4j.rootLogger = debug,stdout
    ​
    ### 输出信息到控制抬 ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.Encoding = utf-8
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
  2. 在resources目录中创建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="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="org/mybatis/example/BlogMapper.xml"/>
        </mappers>
    </configuration>

四,mybatis的开发步骤

  1. 定义实体类

  2. 定义实体类对应的mapper接口,以及相关方法

  3. 在resources目录中编写mapper接口对应的mapper.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="">
        <select id="" resultType="">
    ​
        </select>
    </mapper>
  4. 将mapper.xml文件注册到mybatis的主配置文件中

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

五,细节补充

5.1 properties配置文件的使用

编写 properties 文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis01
jdbc.username=root
jdbc.password=1234

在mybatis的主配置文件中定义properties标签,并引入指定的properties文件

<properties resource="jdbc.properties"/>

修改mybatis主配置文件中datasource标签下property的value值

<dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
 <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>

5.2 给类型起别名

为实体类定义别名,提高开发效率

在mybatis的主配置文件中定义typeAliases

<typeAliases>
  <!-- 为指定的实体类取别名 -->
  <!--<typeAlias type="com.qf.entity.User" alias="User"/>
  <typeAlias type="com.qf.entity.Customer" alias="Customer"/>-->

  <!-- 为指定实体包中的所有实体类取别名,别名就是类名 -->
  <package name="com.qf.entity" />
</typeAliases>
注:在使用别名时不区分大小写

5.3 接口所对应的xml文件的配置

要将接口所对应的xml文件注册在mybatis的主配置文件中

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

如果要配置的xml文件较多可以使用如下方式:

<mappers>
  <package name="com.qf.mapper" />
</mappers>
注:package标签中name属性的值是xml文件所对应的接口所在的包;还需要保证这些xml文件所在的目录结构必须与接口的包结构完全一致

5.4 表的字段名和类的属性名不一致的解决办法

方式一:取别名

<select id="findAllUsers" resultType="User3">
 select uid id,uname name,uage from user3
</select>

方式二:配置resultMap

<resultMap id="userMapper" type="User3" autoMapping="false">
 <id column="uid" property="id"/>
 <result column="uname" property="name"/>
</resultMap>
​
<select id="findAllUsers" resultMap="userMapper">
 select * from user3
</select>

注:

  1. 如果字段名和属性名相同,可以不在resultMap中进行配置,因为在resultMap标签中,有一个默认的属性autoMapping=“true”,它使相同名字的字段和属性自动完成了映射

  2. 如果autoMapping的值设置成的false,即使字段名和属性名相同也无法自动映射,必须手动配置

六,使用xml的方式完成mybatis的crud

6.1 删除

<delete id="接口的方法名" parameterType="">
	sql语句
</delete>

6.2 修改

<update id="接口的方法名" parameterType="">
	sql语句
</update>

6.3 添加

<insert id="接口的方法名" parameterType="">
	sql语句
</insert>

主键自增长

<insert id="saveUser">
 <!--insert into user values(#{id},#{name},#{birthday},#{address},#{tel})-->
 insert into user values(null,#{name},#{birthday},#{address},#{tel})
</insert>

主键回填:

  1. 自增长的主键回填

<insert id="saveUser">
    <!--insert into user values(#{id},#{name},#{birthday},#{address},#{tel})-->
    <!--
        resultType:查询到的主键的类型
        keyProperty:实体类中主键的属性名
        keyColumn:表中主键的字段名
        order:
            取值AFTER表示在执行完insert标签的添加语句之后再执行selectKey标签中的sql语句
            取值BEFORE表示在执行insert标签的添加语句之前先执行selectKey标签中的sql语句
        -->
    <selectKey resultType="int" keyProperty="id" keyColumn="id" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into user values(null,#{name},#{birthday},#{address},#{tel})
</insert>
  1. uuid的主键回填

<insert id="saveUser2">
    <selectKey resultType="String" keyColumn="id" keyProperty="id" order="BEFORE">
        select uuid()
    </selectKey>
    insert into user2 values(#{id},#{name},#{age})
</insert>

注:增删改之后必须提交sqlSession.commit()

6.4 查询

<select id="" resultType="" parameterType="">
 sql语句
</select>

6.4.1 根据参数查询

Customer findCustomerById(Integer id);
<select id="findCustomerById" resultType="Customer">
 select * from customer where id = #{cc}
</select>

注:如果参数列表的个数只有一个,那么占位符#{}中的内容可以是任意的

List<Customer> findCustomersByNameAndAge(String name,int age);
<select id="findCustomersByNameAndAge" resultType="Customer">
 <!--select * from customer where name = #{arg0} and age = #{arg1}-->
 select * from customer where name = #{param1} and age = #{param2}
</select>

对方法的参数使用注解起别名

List<Customer> findCustomersByNameAndSex(@Param("name") String name, @Param("sex") String Sex);
<select id="findCustomersByNameAndSex" resultType="Customer">
 select * from customer where name = #{name} and sex = #{sex}
</select>

将参数存储到Map集合中

List<Customer> findCustomersByNameAgeSex(Map map);
Map map = new HashMap();
map.put("name","宋江");
map.put("sex","男");
map.put("age",88);
<select id="findCustomersByNameAgeSex" resultType="Customer">
 select * from customer where name = #{name} and age = #{age} and sex = #{sex}
</select>

6.4.2 根据对象查询

Customer findCustomerByUserNameAndPassword(Customer c);
Customer c = new Customer();
c.setUsername("15121001484");
c.setPassword("123456");
Customer cus = customerMapper.findCustomerByUserNameAndPassword(c);
<select id="findCustomerByUserNameAndPassword" resultType="Customer">
 select * from customer where username = #{username} and password = #{password}
</select>

6.4.3 模糊查询

List<Customer> findCustomersLikeName(Customer c);
String name = "小";
// 方式一
/*Customer c = new Customer();
     c.setName("%"+name+"%");*/

// 方式二
Customer c = new Customer();
c.setName(name);
List<Customer> cus = customerMapper.findCustomersLikeName(c);
for(Customer cc : cus){
 System.out.println(cc);
}
<select id="findCustomersLikeName" resultType="Customer">
 <!--select * from customer where name like #{name}-->
 <!-- 方式一:此写法必须在java代码中拼接模糊查询 -->


 select * from customer where name like concat('%',#{name},'%')
 <!-- 方式二:此写法不在java代码中拼接模糊查询,在sql语句中拼接 -->


 <!--select * from customer where name like '%${name}%'-->
 <!-- 此写法不推荐,因为底层使用的是Statement,不是PreparedStatement -->
</select>

七,使用注解的方式完成mybatis的crud

@Insert("insert into passenger values (#{id},#{name},#{sex},#{age})")
int savePassenger(Passenger p);
​
@Delete("delete from passenger where id = #{iidd}")
int deletePassenger1(Integer id);
​
@Delete("delete from passenger where id = #{id}")
int deletePassenger2(Passenger p);
​
​
@Update("update passenger set sex = #{sex} , age = #{age} where id = #{id}")
int updatePassenger(Passenger p);
​
​
@Select("select * from passenger where id = #{id}")
Passenger findPassengerById(Passenger p);
​
@Select("select count(*) from passenger")
int findPassengerCount();
​
//@Select("select * from passenger where name like #{name}")
@Select("select * from passenger where name like concat(#{name},'%')")
List<Passenger> findPassengersLikeName(Passenger p);

八,配置druid连接池

步骤:

  1. 添加druid依赖

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.9</version>
    </dependency>
  2. 自定义连接池工厂类

    public class MyDruidDataSourceFactory extends PooledDataSourceFactory{
        public MyDruidDataSourceFactory(){
            this.dataSource = new DruidDataSource();
        }
    }
  3. 修改mybatis的主配置文件

    <dataSource type="com.qf.utils.MyDruidDataSourceFactory">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </dataSource>

九,缓存cache

概念:

内存中的一片存储空间,将频繁查询的结果临时保存在内存中,以便于再次访问

对比:

没有缓存:用户在访问相同数据,执行相同的查询语句时,需要再次对数据库发起访问,会产生额外的IO操作,额外的磁盘读写会降低效率,消耗额外的资源。

有缓存:首次访问时,将查询到的结果存储到缓存中,再次访问相同数据时,直接访问缓存而不再与数据库产生IO操作,从而减少了磁盘的读写,提高了效率

9.1 一级缓存

SqlSession级别的缓存,指的是当SqlSession向数据库发起查询动作时,查询的结果就会被保存到一级缓存中,当同一个SqlSession再次向数据库发起结构相同的查询动作时,不再连接数据库执行查询动作,而是直接从缓存中返回数据。

注:一级缓存不需要做任何配置,mybatis默认开启了一级缓存

9.2 二级缓存

SqlSessionFactory级别的缓存,指的是根据同一个SqlSessionFactory创建的任何一个SqlSession对象在向数据库发起查询动作时,查询的结果都会保存在二级缓存中

开启二级缓冲:

  1. 在mybatis的主配置文件中配置设置二级缓存的开启

    <!-- 开启全局的二级缓存,任何一个mapper.xml文件都允许使用二级缓存 -->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 在需要开启二级缓存的mapper.xml文件配置:

    <mapper namespace="com.qf.mapper.UserMapper">
    ​
        <cache />
    ​
        <select id="findAllUsers" resultType="User">
            select * from user
        </select>
    </mapper>

注:

  1. 使用二级缓存进行存储实体类必须实现序列化

  2. 如果某条sql语句要查询的是实时的最新数据,那么可以禁止缓存,方式如下:

<select id="findAllUsers" resultType="User" useCache="false">
    select * from user
</select>

十,动态sql

10.1 sql 标签

<!--
	<sql id="user3_refid">
     uid id,uname name,uage
 </sql>

 <select id="findAllUsers" resultType="User3">
     select <include refid="user3_refid"/> from user3
 </select>
-->

<resultMap id="user3Map" type="User3">
 <id column="uid" property="id" />
 <result column="uname" property="name" />
 <result column="uage" property="uage" />
</resultMap>

<sql id="user3Refid">
 uid,uname,uage
</sql>

<select id="findAllUsers" resultMap="user3Map">
 select <include refid="user3Refid"/> from user3
</select>

10.2 where 标签

特点:

  1. 如果where标签中没有任何一个if标签的test表达式的结果为true,那么where关键字不会出现

  2. 只要where中有一个if标签的test表达式的结果为true,那么where关键字就会出现,并且会删除第一个if标签中的and或者or关键字

10.3 Set 标签

10.4 forEach 标签

十一,mybatis中的多表

11.1 一对一

在数据库中,需要在任意一方定义外键指向另一方的主键

在两个实体类中,都必须将另一个类的对象作为本类的属性

11.2 一对多

在数据库中,需要在多的一方定义外建指向一的一方的主键

实体类中,在多的一方中将一的一方的对象作为本类的属性;在一的一方中将多的一方的对象集合作为本类的属性

11.3 多对多

在数据库中,需要创建一张中间表,中间表至少包含两个字段分别指向两张主表的主键

实体类中,需要在任何一方将另一方法的对象集合作为本类的属性

十二,PageHelper

概念:mybatis中专门用于分页的插件,使用非常方便,现在由github托管。

使用步骤:

  1. 添加依赖

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.1.12</version>
    </dependency>
  2. 在mybatis的主配置文件中配置插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    <!-- 配置的是pagehelper的分页拦截器,当我们在执行查询语句前,只要使用到了PageHelper中的功能startPage(n,m),当前查询语句就会先被拦截下来,根据startPage中的参数自动的将查询语句补充完整 -->

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值