Mybaits
MyBatis 是一款优秀的持久层框架(ORM框架),它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所 有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接 口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
目录结构
引入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
配置mybatis核心文件
<?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>
<settings>
<!--开启下划线转驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--配置SQL输出-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--配置别名,指定包下的-->
<typeAliases>
<package name="com.cd.entity"/>
</typeAliases>
<!-- 支持多环境 default 指明使用那套环境, 开发中有测试环境和线上环-->
<environments default="development">
<!--具体某个配置环境 可有多个 -->
<environment id="development">
<!--使用mybatis 自己的事务管理器-->
<transactionManager type="JDBC"/>
<!--使用mybatis自己的简单连接池 -->
<dataSource type="POOLED">
<!-- JDBC连接的几个属性 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--引入mapper 文件 -->
<mappers>
<mapper resource="mybatis-Mapper.xml"/>
</mappers>
</configuration>
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" >
<!--
名字空间,自己定义,用户管理 SQL语句,防止命名冲突(如果是基于接口映射,则为接口的全限定名)
-->
<mapper namespace="com.cd.Dao.UserMapper">
<!--
select 声明查询语句
id:该sql的唯一表示,调用时使用
parameterType: 声明参数类型,使用Java的数据类型全限定名,mybatis为常用数据类型取有别名,可以使 用类型别名。
resultType: 声明返回类型,使用类型的全限定名,也可使用别名。
-->
<select id="findUserByID" parameterType="int" resultType="com.cd.entity.User">
SELECT * FROM TB_USER WHERE ID= #{id}
</select>
<select id="findAll" resultType="com.cd.entity.User">
select * from tb_user
</select>
</mapper>
//#{ id } 如果是简单参数 可以随意取名,如果是对象类型参数则为属性名称
测试类
import com.cd.Dao.UserMapper;
import com.cd.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
public class Apptest {
@Test
public void test1() throws IOException {
// 创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
// 获得 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 获得Mapper 接口实例
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行SQL
sqlSession.delete("com.cd.Dao.UserMapper.deleteUer", 5);
User user = new User(null, "张三", 200.00);
//userMapper.addUser(user);
//userMapper.deleteUer(3);
sqlSession.commit();
}
}
Mybatis 提供了两种交互方式:
- 直接使用 sqlSession 的相关API。
- 使用Mapper 接口的方式(推荐使用)
定义Mapper接口(就是以前的Dao接口)
package com.cd.Dao;
import com.cd.entity.User;
import java.util.List;
public interface UserMapper {
public int addUser( User user);
public int updateUser(User user);
public int deleteUer(int id);
public User findUserByID(int id);
public List<User> findAll();
}
基于Mapper接口的方式,实际上是Mybatis通过生成代理对象实现了Mapper接口中的方法,而实现的方法与 Mapper xml文件的 SQL进行绑定执行,简单的说就是把 Maper接口中的抽象方法与SQL语句进行绑定。
- namespace=“com.qfedu.app.dao.UserMapper” 执向的接口(接口的全类名或别名)
- SQL标签的id 指向接口中的抽象方法( 方法名字)
参数与返回值
当使用单个简单类型参数[ 基本数据类型+ String ] , mapper 使用 #{ 任意名称 }
当使用单个实体类型参数 mapper 使用 #{ 属性 }
当使用多个简单类型作为参数 mapper 使用 #{ param1 } ,或者接口参数使用注解@Param(“参数名”) ,这样 mapper 使用 #{参数名 }
当使用map作为参数 mapper 使用 #{key}
当使用List 作为参数 mapper 使用 #{ list[i] }
获得自增长ID
<insert id="addUserBackId" parameterType="User" useGeneratedKeys="true" keyProperty="id" >
insert into tb_user(username,money,user_age) values( #{username},# {money,jdbcType=DOUBLE},#{userAge} )
</insert>
//当sql执行完毕获得自动增长的ID 回填到入参模型指定的 keyProperty 属性身上。
使用HashMap 做返回值
<select id="findUserReturnMap" resultType="hashmap">
SELECT * FROM TB_USER WHERE ID= #{id}
</select>
关联映射
一对一的关联映射
bean
package com.cd.entity;
import lombok.Data;
@Data
public class OrderItem {
private Integer did;
private Integer oid;
private Product pro;
}
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" >
<mapper namespace="com.cd.dao.EmployeeMapper">
<!--方式一:通过别名进行级联关系映射 -->
<select id="findAll" resultType="Employee">
select emp_no,ename,salary,d.dept_no as 'dept.deptNo',dname as 'dept.dname',loc as 'dept.loc'
from tb_department d ,tb_employee e
where d.dept_no=e.dept_no
</select>
<!--方式二,通过结果集映射
ID:唯一,被其他resultap引用,一般用于主键,result用于其他
TYPE:
autoMapping:自动映射
extends:继承其他resultMap
-->
<resultMap id="baseMap" type="Employee">
<id column="emp_no" property="empNo"/>
<result column="ename" property="ename"/>
<result column="salary" property="salary"/>
</resultMap>
<resultMap id="EmployeeDetail" type="Employee" extends="baseMap">
<!– <id column="emp_no" property="empNo"/>
<result column="ename" property="ename"/>
<result column="salary" property="salary"/>–>
<!–级联–>
<association property="dept" javaType="Department" autoMapping="true">
<!– <id column="dept_no" property="dept_no"/>
<result column="dname" property="dname"/>
<result property="loc" column="loc"/>–>
</association>
</resultMap>
<select id="findAll" resultMap="EmployeeDetail">
select emp_no,ename,salary,d.dept_no,dname,loc
from tb_employee e,tb_department d
where e.dept_no=d.dept_no
</select>
<!--方式三:基于分步骤级联查询-->
<resultMap id="baseMap" type="com.cd.entity.Employee">
<id column="emp_no" property="empNo"/>
<result column="ename" property="ename"/>
<result column="salary" property="salary"/>
</resultMap>
<resultMap id="EmployeeDeatil" type="Employee" extends="baseMap">
<association property="dept" column="dept_no" autoMapping="true" select="com.cd.dao.DepartmentMapper.findById">
</association>
</resultMap>
<select id="findAll" resultMap="EmployeeDeatil">
select *
from tb_employee
</select>
</mapper>
一对多关联映射
- 基于结果集映射
- 基于分别查询
bean
package com.cd.entity;
import lombok.Data;
import java.util.List;
@Data
public class Order {
private Integer oid;
private Double total;
private String user;
private List<OrderItem> oi;
}
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" >
<mapper namespace="com.cd.dao.OderMapper">
<resultMap id="OrderDetail" type="Order">
<id property="oid" column="oid"/>
<result property="total" column="total"/>
<result property="user" column="user"/>
<!--oi属性赋值-->
<collection property="oi" ofType="OrderItem">
<id property="oid" column="oid"/>
<result property="did" column="did"/>
<association property="pro" javaType="Product" autoMapping="true">
</association>
</collection>
</resultMap>
<select id="findAllOrder" resultMap="OrderDetail">
SELECT
*
FROM
tb_order t
LEFT JOIN tb_order_item o ON t.oid = o.oid
LEFT JOIN tb_product p ON o.pid = p.pid
</select>
</mapper>
注解配置
@Insert("insert into tb_employee(ename,salary,dept_no) values(#{ename},#{salary},#{ dept.deptNo})")
public int add( Employee employee );、
@Delete("delete from tb_employee where emp_no=#{empNo}")
public int delete( Integer empNo );
@Update("update tb_employee set ename=#{ename} , salary=#{salary}, dept_no=#{ dept.deptNo } where emp_no=#{empNo}") p
ublic int update( Employee employee );
@Select("select * from tb_employee where salary between #{min} and #{max} ")
public List<Employee> findUserBySalaryRange(@Param("min") double min, @Param("max") double max );
Mybatis动态SQL
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条 件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利 用动态 SQL 这一特性可以彻底摆脱这种痛苦。 动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了 解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表 达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim(where,set)
- foreach
if示例
<select id="findEmpByCondition" resultType="com.cd.entity.Employee">
SELECT * FROM TB_EMPLOYEE WHERE 1=1
<if test="ename!=null and ename!='' ">
AND ename=#{ename}
</if>
<if test=" salary != null ">
AND salary>#{salary}
</if>
<if test=" dept.deptNo !=null ">
AND dept_no = #{dept.deptNo}
</if>
</select>
choose, when, otherwise(三者选一)
<select id="findAllOrder" resultMap="OrderDetail">
SELECT * FROM TB_EMPLOYEE WHERE
<choose>
<when test="ename!=null and ename!=''">
ename = #{ename}
</when>
<when test="salary!=null">
salary = #{salary}
</when>
<otherwise>
salary = #{salary}
</otherwise>
</choose>
where示例(如果条件成立添加where 同时自动去掉前面的AND)
<select id="findAllOrder" resultMap="OrderDetail">
SELECT * FROM TB_EMPLOYEE
<where>
<if test="ename!=null and ename!=''">
AND ename=#{ename}
</if>
<if test=" salary != null ">
AND salary>#{salary}
</if>
<if test="dept.deptNo !=null ">
AND dept_no = #{dept.deptNo}
</if>
</where>
</select>
trim 示例
-
prefix : 给包裹的sql语句加上前缀.
-
suffix : 给包裹的sql语句加上后缀.
-
prefixOverrides: 如果包裹的sql语句是空语句(经常出现在 if 判断为否的情况下),取消指定的前缀,如where.
-
suffixOverrides: 如果包裹的sql语句是空语句(经常出现在 if 判断为否的情况下),取消指定的后缀,如and | or. 逗号等
<select id="findAllOrder" resultMap="OrderDetail">
SELECT * FROM TB_EMPLOYEE
<trim prefix="where" suffixOverrides="AND|OR">
<if test="ename!=null and ename!=''">
ename=#{ename} AND
</if>
<if test=" salary != null ">
salary>#{salary} AND
</if>
<if test="dept.deptNo !=null ">
dept_no = #{dept.deptNo} AND
</if>
</trim>
</select>
set 示例
<select id="updateByCondition" resultMap="OrderDetail">
UPDATE TB_EMPLOYEE
<set>
<if test="ename!=null and ename!=''">
ename=#{ename}
</if>
<if test=" salary != null ">
salary>#{salary}
</if>
<if test="dept.deptNo !=null ">
dept_no = #{dept.deptNo}
</if>
</set>
where emp_no=#{empNo}
</select>
foreach示例
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意:你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<select id="findEmpEmpNo" resultType="com.qfedu.app.entity.Employee">
select * from tb_employee where emp_no in
<foreach collection="ids" item="it" open="(" close=")" separator=",">
#{it}
</foreach>
</select>