一,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环境
在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>建议使用日志,
引入日志的依赖
<!-- 日志的依赖 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
在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在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的开发步骤
定义实体类
定义实体类对应的mapper接口,以及相关方法
在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>将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>注:
如果字段名和属性名相同,可以不在resultMap中进行配置,因为在resultMap标签中,有一个默认的属性
autoMapping=“true”
,它使相同名字的字段和属性自动完成了映射如果
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>
主键回填:
自增长的主键回填
<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>
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连接池
步骤:
添加druid依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency>自定义连接池工厂类
public class MyDruidDataSourceFactory extends PooledDataSourceFactory{ public MyDruidDataSourceFactory(){ this.dataSource = new DruidDataSource(); } }修改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对象在向数据库发起查询动作时,查询的结果都会保存在二级缓存中
开启二级缓冲:
在mybatis的主配置文件中配置设置二级缓存的开启
<!-- 开启全局的二级缓存,任何一个mapper.xml文件都允许使用二级缓存 --> <settings> <setting name="cacheEnabled" value="true"/> </settings>在需要开启二级缓存的mapper.xml文件配置:
<mapper namespace="com.qf.mapper.UserMapper"> <cache /> <select id="findAllUsers" resultType="User"> select * from user </select> </mapper>注:
使用二级缓存进行存储实体类必须实现序列化
如果某条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 标签
特点:
如果where标签中没有任何一个if标签的test表达式的结果为true,那么where关键字不会出现
只要where中有一个if标签的test表达式的结果为true,那么where关键字就会出现,并且会删除第一个if标签中的and或者or关键字
10.3 Set 标签
10.4 forEach 标签
十一,mybatis中的多表
11.1 一对一
在数据库中,需要在任意一方定义外键指向另一方的主键
在两个实体类中,都必须将另一个类的对象作为本类的属性
11.2 一对多
在数据库中,需要在多的一方定义外建指向一的一方的主键
实体类中,在多的一方中将一的一方的对象作为本类的属性;在一的一方中将多的一方的对象集合作为本类的属性
11.3 多对多
在数据库中,需要创建一张中间表,中间表至少包含两个字段分别指向两张主表的主键
实体类中,需要在任何一方将另一方法的对象集合作为本类的属性
十二,PageHelper
概念:mybatis中专门用于分页的插件,使用非常方便,现在由github托管。
使用步骤:
添加依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.12</version> </dependency>在mybatis的主配置文件中配置插件
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> <!-- 配置的是pagehelper的分页拦截器,当我们在执行查询语句前,只要使用到了PageHelper中的功能startPage(n,m),当前查询语句就会先被拦截下来,根据startPage中的参数自动的将查询语句补充完整 -->