今日内容
  1. 动态SQL语句
    1. Xml方式
    2. 注解方式
  2. MyBatis的缓存
  3. MyBatis的关联查询
  4. MyBatis逆向工程
动态SQL语句
动态SQL是什么
就是相对与固定SQL。就是通过传入的参数不一样,可以组成不同结构的SQL语句. 这种根据参数的条件修改SQL结构的SQL语句,我们称为动态SQL语句.
 
动态SQL有什么用
  1. 根据条件组装不同结构的SQL语句,可以提高SQL代码的重用性.
  2. 满足某些特定需求,如,条件判断查询
 
基于XML的实现
标签包括
<sql> 用于声明公有的SQL语句块.,在操作标签中使用<include>调用 [不建议用]
不建议的原因,会导致代码难以维护。
<if> 类似java if(){},用于判断
<foreach>:类似java的foreach循环,一般用户批量处理的SQL语句
<trim> :切割标签,主要用于切割关键字的头和尾的字符.新版的Mybatis使用的几率很少.
<set>:使用 set标签就是SQL语言的set关键字,可以在update 的时候set 关键字后面的,逗号可以自动忽略
<where>:使用where标签作为SQL语言的where关键字,好处如果where后面的条件都不成立,忽略where关键字.
<choose> <when> <otherwise> : java的swithc case
接口文件

package cn.zj.mybatis.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import cn.zj.mybatis.pojo.User;
public interface UserMapper { /**
* 根据条件查询结果
* @param user
* @return
*/
List<User> selectByCondition(User user); /**
* 根据提交查询总数
* @param user
* @return
*/
Long selectTotalByCondition(User user); /**
* 修改用户
* @param user
* @return
*/
int updateUserByNotNull(User user); /**
* 批量删除用户
* @param ids
* @return
*/
int deleteByIds(@Param("ids")Integer[] ids); /**
* 批量插入
* @param users
* @return
*/
int insertByBatch(@Param("users")List<User> users); }
映射文件
<?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 配置 mybatis 表的映射
namespache :命名空间(和对应映射的接口的 全限定名一样),通俗讲,当前映射文件的唯一标识
全限定名 : 包名+接口名/类名
-->
<mapper namespace="cn.zj.mybatis.mapper.UserMapper"> <!-- sql片段 -->
<sql id="condition_sql">
<!-- where 标签 -->
<where>
<if test="name !=null">
name like concat('%',#{name},'%')
</if>
<if test="password !=null">
and password = #{password}
</if>
<if test="age !=null">
and age = #{age}
</if>
</where> </sql> <!-- 多条件查询 -->
<select id="selectByCondition" parameterType="cn.zj.mybatis.pojo.User" resultType="cn.zj.mybatis.pojo.User">
select * from user
<!-- 引入sql片段 -->
<include refid="condition_sql"/>
</select> <!-- 多条件查询总数 -->
<select id="selectTotalByCondition" parameterType="cn.zj.mybatis.pojo.User" resultType="long">
select count(*) from user
<!-- where 标签 -->
<include refid="condition_sql"/>
</select> <!-- 修改用户信息(数据不为空的修改) -->
<update id="updateUserByNotNull" parameterType="cn.zj.mybatis.pojo.User">
update user
<set>
<if test="name !=null">
name = #{name},
</if>
<if test="password !=null">
password = #{password},
</if>
<if test="age !=null">
age = #{age},
</if>
</set>
where id = #{id}
</update> <!-- 批量删除 -->
<delete id="deleteByIds" parameterType="integer">
<!-- sql : delete from user where id in (1,2,3,4) -->
delete from user where id in <!-- 动态sql语句值 foreach --> <foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete> <!-- 批量插入 -->
<delete id="insertByBatch" parameterType="list">
<!-- insert into user (name,password,age) values (xx,xx,xx),(xx1,xx1,xx1) --> insert into user (name,password,age) values <foreach collection="users" item="user" separator="," >
(#{user.name},#{user.password},#{user.age})
</foreach>
</delete>
</mapper>
测试代码
 
package cn.zj.mybatis.test;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import cn.zj.mybatis.mapper.UserMapper;
import cn.zj.mybatis.pojo.User;
import cn.zj.mybatis.util.MyBatisUtil;
public class UserMapperTest {
@Test
public void testSelectByCondition() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
// user.setAge(30);
user.setName("哥");
List<User> users = userMapper.selectByCondition(user);
for (User user2 : users) {
System.out.println(user2);
} Long totalCount = userMapper.selectTotalByCondition(user);
System.out.println(totalCount); //关闭sesison
session.close();
}
@Test
public void testInsert() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user1 = new User(null, "西门吹雪", "xmcx", 25);
User user2 = new User(null, "东方不败", "dfbb", 30);
List<User> users = new ArrayList<>(); users.add(user1);
users.add(user2);
// 3. 执行UserMapper的批量插入方法
int row = userMapper.insertByBatch(users);
System.out.println(row); // 4.提交事务(MyBatis是手动提交事务)
session.commit();
// 5.关闭Session
session.close();
}
@Test
public void testUpdate() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User(1, null, "xf", null);
// 3.执行修改方法
int row = userMapper.updateUserByNotNull(user);
System.out.println(row);
// 4.提交事务
session.commit();
// 5.关闭session
session.close();
}
@Test
public void testDelete() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
Integer[] ids = { 2, 3, 5 };
// 3.执行修改方法
int row = userMapper.deleteByIds(ids);
System.out.println(row);
// 4.提交事务
session.commit();
// 5.关闭session
session.close();
}
}
 
基于注解方式实现
动态sql除了支持xml方式以外,还是支持使用纯注解的方式
主要一下四个注解+对应动态sql语句的类文件
  1. @SelectProvider 动态查询SQL语句对应注解
  2. @InsertProvider 动态插入SQL语句对应注解
  3. @UpdateProvider 动态修改SQL语句对应注解
  4. @DeleteProvider 动态删除SQL语句对应注解
 
接口映射文件
 
package cn.zj.mybatis.mapper;
import java.util.List;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import cn.zj.mybatis.pojo.User;
import cn.zj.mybatis.pojo.UserProvider;
public interface UserMapper { /*
* @SelectProvider(type=UserProvider.class,method="")
* @SelectProvider 查询动态sql语句的 注解
* type : 编写动态sql语句的类对应的字节码
* method : 编写动态sql语句类对应的方法名称
* 此方法返回的是一个String字符串,字符串就是拼接sql语句
*/
@SelectProvider(type=UserProvider.class,method="selectByCondition")
List<User> selectByCondition(User user); /**
* 根据条件查询总数
* @param user
* @return
*/
@SelectProvider(type=UserProvider.class,method="selectTotalByCondition")
Long selectTotalByCondition(User user); /**
* 修改用户信息,参数不为空的数据才会修改
* @param user
* @return
*/
@UpdateProvider(type=UserProvider.class,method="updateByNotNull")
int updateByNotNull(User user); /**
* 批量删除
* @param ids
* @return
*/
@DeleteProvider(type=UserProvider.class,method="deleteByIds")
int deleteByIds(@Param("ids")List<Integer> ids); /**
* 批量插入
* @param users
* @return
*/
@InsertProvider(type=UserProvider.class,method="batchInsert")
int batchInsert(@Param("users")List<User> users);
}
 
动态sql语句文件
package cn.zj.mybatis.pojo;
import java.util.List;
import org.apache.ibatis.annotations.Param;
/*
* UserMapper接口映射对应的动态SQL语句的的类
*/
public class UserProvider { /**
* 返回条件查询对应的动态sql语句
* @param user 条件参数
* @return sql
*/
public String selectByCondition(User user) {
StringBuilder sb = new StringBuilder();
sb.append("select * from user WHERE 1 = 1 ");
//动态拼接SQL语句
if(user.getName() !=null) {
//使用OGNL表达式获取 对象属性的值
sb.append("AND name like concat('%',#{name},'%')");
}
if(user.getAge() !=null) {
sb.append("AND age = #{age}");
} return sb.toString();
} public String selectTotalByCondition(User user) {
StringBuilder sb = new StringBuilder();
sb.append("select count(1) from user WHERE 1 = 1 ");
//动态拼接SQL语句
if(user.getName() !=null) {
//使用OGNL表达式获取 对象属性的值
sb.append("AND name like concat('%',#{name},'%')");
}
if(user.getAge() !=null) {
sb.append("AND age = #{age}");
} return sb.toString();
} public String updateByNotNull(User user) {
StringBuilder sb = new StringBuilder();
sb.append("update user set "); if(user.getName() !=null) {
sb.append("name = #{name},");
}
if(user.getPassword() !=null) {
sb.append("password = #{password},");
}
if(user.getAge() !=null) {
sb.append("age = #{age},");
}
//删除最后一个多余的逗号
sb.deleteCharAt(sb.length()-1); sb.append(" where id = #{id}"); return sb.toString();
} public String deleteByIds(@Param("ids")List<Integer> ids) {
StringBuilder sb = new StringBuilder();
//delete from user where id in (1,3,5,6);
sb.append("delete from user where id in ("); for (int i = 0; i < ids.size(); i++) {
//使用OGNL 表达式获取集合的每一个数据 #{ids[0]} #{ids[1]} #{ids[2]}...
sb.append("#{ids["+i+"]},");
} //删除最后一个多余的逗号
sb.deleteCharAt(sb.length()-1); sb.append(")");
return sb.toString();
} public String batchInsert(@Param("users")List<User> users) {
StringBuilder sb = new StringBuilder();
// insert into user (name,password,age) values
// (xxx,x,xx),(xxx1,x1,xx1),(xxx2,x2,xx2),
sb.append("insert into user (name,password,age) values "); for (int i = 0; i < users.size(); i++) {
sb.append("(");
//姓名
sb.append("#{users["+i+"].name},");
//密码
sb.append("#{users["+i+"].password},");
//年龄
sb.append("#{users["+i+"].age}");
sb.append("),");
}
//删除最后一个多余的逗号
sb.deleteCharAt(sb.length()-1);
System.out.println("SQL :"+sb.toString());
return sb.toString();
}
}
测试代码
package cn.zj.mybatis.test;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import cn.zj.mybatis.mapper.UserMapper;
import cn.zj.mybatis.pojo.User;
import cn.zj.mybatis.util.MyBatisUtil;
public class UserMapperTest {
@Test
public void testSelectByCondition() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
// user.setAge(30);
user.setName("哥");
List<User> users = userMapper.selectByCondition(user);
for (User user2 : users) {
System.out.println(user2);
}
// 查询总数
Long totalCount = userMapper.selectTotalByCondition(conditionUser);
System.out.println("totalCount:" + totalCount);
// 关闭session
session.close();
}
@Test
public void testInsert() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user1 = new User(null, "西门吹雪", "xmcx", 25);
User user2 = new User(null, "东方不败", "dfbb", 30);
List<User> users = new ArrayList<>(); users.add(user1);
users.add(user2);
// 3. 执行UserMapper的批量插入方法
int row = userMapper.insertByBatch(users);
System.out.println(row); // 4.提交事务(MyBatis是手动提交事务)
session.commit();
// 5.关闭Session
session.close();
}
@Test
public void testUpdate() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User(5, null, "xf", null);
// 3.执行修改方法
int row = userMapper.updateUserByNotNull(user);
System.out.println(row);
// 4.提交事务
session.commit();
// 5.关闭session
session.close();
}
@Test
public void testDelete() throws Exception {
// 1.创建SqlSession对象
SqlSession session = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
Integer[] ids = { 2, 3, 5 };
// 3.执行修改方法
int row = userMapper.deleteByIds(ids);
System.out.println(row);
// 4.提交事务
session.commit();
// 5.关闭session
session.close();
}
}
 
缓存
在Mybatis里面,所谓的缓存就是将已经查询过的记录放在内存的缓冲区或文件上,这样如果再次查询,可以通过配置的策略,命中已经查询过的记录.从而提高查询的效率.
缓存作用
提高查询的效率.
一级缓存
Mybatis的缓存分为一级缓存\ 二级缓存
 
一级缓存:所谓的一级缓存就是会话(SqlSesion对象)级别的缓存,就是同一个会话,如果已经查询过的数据会保存一份在内存中,如果会话没有关闭,再次调用同样的方法查询,不会再查询数据库,而是直接从缓存中取出之前查询的数据.
 
一级缓存默认是打开的,而且是关闭不了的.
 
如何清空一级缓存.
1.关闭会话.close()
2.进行了操作(增删改),提交了commit();
3.手工清除缓存clearCache()
测试代码
@Test
public void testselectAll() {
// 1.创建SqlSession对象
//SqlSesion对象默认就开启了一级缓存,将已经查询过的数据就缓存到SqlSession的缓存区域
//在此会话中如果再次发送同样的请求,那么直接从缓存区域获取数据,不会再发送SQL语句了 SqlSession session1 = MyBatisUtil.openSession();
//SqlSession session2 = MyBatisUtil.openSession();
// 2.创建UserMapper接口的代理对象
UserMapper mapper1 = session1.getMapper(UserMapper.class); //UserMapper mapper2 = session2.getMapper(UserMapper.class);
//3.执行查询方法
List<User> users1 = mapper1.selectAll(); //手动清理缓存
session1.clearCache(); List<User> users2 = mapper1.selectAll();
}
 
二级缓存
一级缓存是SqlSession对象级别,在每一次会话中有效
 
二级缓存是 SqlSessionFactory级别,在整个应用都有效,可以在多个会话有效
MyBatis本身并没有实现二级缓存
 
二级缓存需要第三方缓存提供商的支持
Ehcache -第三方缓存(Hibernate框架默认就是支持)
 
学习地址
http://www.mybatis.org/ehcache-cache/
 
下载ehcache
https://github.com/mybatis/ehcache-cache/releases

配置开启二级缓存
MyBatis开启二级缓存新版本已经默认支持开启二级缓存.可以不改
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
 
 
导入Ehcachejar包
Ehcache依赖 slfj 日志框架,必须要导入slfj的两个jar包
创建 ehcache.xml配置文件
Ehcache有自己的配置文件,在src下面创建ehcache.xml 配置文件
<ehcache>
<!-- 缓存的磁盘位置 -->
<diskStore path="D:/mybatis_cache"/>
<!-- 默认的缓存策略: 如果开发者在某一个需要缓存的文件配置了自定义缓存,就不使用默认的,如果没有配置,就使用默认缓存策略-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
在映射文件中配置<cache>以及配置对应的缓存策略
<mapper namespace="cn.zj.mybatis.dao.UserMapper">
 
<!-- 当前表的映射开启支持二级缓存,并设置相关的缓存提供商,以及缓存的相关配置 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache" >
<!--最大的空闲时间 -->
<property name="timeToIdleSeconds" value="10000"/>
<!-- 最大的在线时间 -->
<property name="timeToLiveSeconds" value="20000"/>
<!-- 内存的大小 b字节 m1 =1024k 1k=1024b -->
<property name="maxEntriesLocalHeap" value="2000000"/>
<!-- 文件的大小 b字节-->
<property name="maxEntriesLocalDisk" value="20000000"/>
<!-- 算法 LRU:最少使用优先, "LFU" or "FIFO:先进先出 -->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
<select id="selectAll" resultType="User">
select * from user
</select>
</mapper>
因为二级缓存可以缓存到文件(将对象序列化到本地),涉及到对象序列化,那么对应的javaBean对象就必须实现
public class User implements Serializable{
private static final long serialVersionUID = -8366151150155170110L;
}
缓存的命中率
命中率= 从缓存中获取数据的次数/ 查询的总次数
如 : 两次查询 从缓中获取一次
0.5 = 1/2;
0.666666 = 2/3;
命中率越高缓存效果越好
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - ==> Preparing: select * from user where id = ?
DEBUG [main] - ==> Parameters: 3(Integer)
DEBUG [main] - <== Total: 1
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.5
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.6666666666666666
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.75
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8333333333333334
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8571428571428571
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.875
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8888888888888888
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.9
MyBatis的对象关系映射(难点重点)
在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值连接), 等值连接 表与表之间有一个外键关键
但是程序中最终获取的表封装的对象, 对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系
对象之间关系主要是四种
一对一 关系
一个人对应身份证id,一个QQ号对应一个QQ空间
一对多 关系
一个部门对应多个员工
多对一 关系
多个员工对应一个部门
多对多 关系
多个学生对应多个老师,多个学生对应多个课程
什么关系应该从哪个对象作为中心点来看
一对多, 以one方作为中心点
MyBatis框架支持多表查询封装对象之间关系
<collection> 一对多查询
<association>多对一和一对一查询
准备多表,表之间有外键关系(员工表和部门表)
员工表
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`dept_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
部门表
CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
多对一查询
public class Employee {
private Integer id;
private String name;
//以员工为中心 :
多个员工对应一个部门,多对一关系,many2one
//员工与部门的对象关系
private Department dept;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", dept=" + dept + "]";
}
}
public class Department {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
Man2oneMapper.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 : 命名空间,通俗讲,每个映射文件唯一的标识名称
-->
<mapper namespace="cn.zj.mybatis.mapper.Many2OneMapper">
<select id="selectByEmpId" parameterType="Integer" resultMap="emp_map">
 
select * from employee where id = #{id}
 
</select>
 
 
<resultMap type="cn.zj.mybatis.pojo.Employee" id="emp_map">
 
<id column="id" property="id"/>
<result column="name" property="name"/>
 
<!--
需要映射部门对象属性
private Department dept;
 
解决方案,使用关联查询
<association property="dept" column="dept_id" select=""/>
property :需要映射的属性
column :要映射属性对应的外键列
select :对应的查询方案, 对应查询的命名空间+.+功能id
-->
<association property="dept" column="dept_id"
select="cn.zj.mybatis.mapper.Many2OneMapper.findDeptById"/>
 
</resultMap>
 
<!-- 根据部门Id查询对应的部门对象 -->
<select id="findDeptById" parameterType="Integer" resultType="cn.zj.mybatis.pojo.Department">
select * from department where id = #{dept_id}
</select>
 
</mapper>
一对多查询
以部门为中心查询部门的所有信息(包括员工),一个部门对应多个员工
 
Pojo对象
public class Department {
private Integer id;
private String name;
 
//以部门为中心:一个部门对应多个与员工 一对多关系 (one2many)
private List<Employee> emps;
 
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + ", emps=" + emps + "]";
}
}
public class Employee {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}
N+1方式
N+1 : N 就是当前需要查询结果对应发送的SQL语句的条数
+1 关联查询数据需要额外多发一条SQL语句才能查询出对应的结果
映射代码
<?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 : 命名空间,通俗讲,每个映射文件唯一的标识名称
-->
<mapper namespace="cn.zj.mybatis.mapper.One2ManyMapper">
<select id="selectDeptById" parameterType="Integer" resultMap="dept_map">
 
select * from department where id = #{id}
 
</select>
 
<!-- 手动映射 -->
<resultMap type="cn.zj.mybatis.pojo.Department" id="dept_map">
<id column="id" property="id"/>
<result column="name" property="name"/>
 
<!-- private List<Employee> emps;
集合属性映射
<collection property="emps" column="id" select=""/>
property:需要映射得集合 emps
column : 部门的主键 id
select : 关联查询,去根据部门id查询出对应的员工
值关联查询功能的 命名空间+.+功能id
-->
<collection property="emps" column="id" select="cn.zj.mybatis.mapper.One2ManyMapper.selectUsersByDeptId"/>
 
</resultMap>
 
 
<!-- 关联查询的功能
根据部门的id查询所有的员工
-->
<select id="selectUsersByDeptId" parameterType="integer" resultType="cn.zj.mybatis.pojo.Employee">
select * from employee where dept_id = #{id}
</select>
</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 : 命名空间,通俗讲,每个映射文件唯一的标识名称
-->
<mapper namespace="cn.zj.mybatis.mapper.One2ManyMapper">
<select id="selectDeptById" parameterType="Integer" resultMap="dept_map">
 
select e.id e_id ,e.name e_name,d.id d_id,d.name d_name
from department d JOIN employee e ON d.id = e.dept_id WHERE d.id = #{id};
 
</select>
 
<!-- 手动映射 -->
<resultMap type="Department" id="dept_map">
<id column="d_id" property="id"/>
<result column="d_name" property="name"/>
 
<!-- private List<Employee> emps;
集合属性映射
<collection property="emps" column="id" select=""/>
property:需要映射得集合 emps
column : 部门的主键 id
ofType : 需要映射集合的泛型的类型
-->
 
<collection property="emps" ofType="Employee">
<!-- 集合泛型类型对应的pojo的主键列映射 ,Employee的主键列映射 -->
<id column="e_id" property="id"/>
<!-- 集合泛型类型对应的pojo的非主键列映射 ,Employee的非主键列映射 -->
<result column="e_name" property="name"/>
</collection>
 
</resultMap>
 
</mapper>
运行结果
只会发送一条SQL语句
DEBUG [main] - ==> Preparing: select e.id e_id ,e.name e_name,d.id d_id,d.name d_name from department d JOIN employee e ON d.id = e.dept_id WHERE d.id = ?;
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 2
Department [id=1, name=总经办, emps=[Employee [id=1, name=乔峰], Employee [id=3, name=段誉]]]
 
MyBatis的逆向工程
MyBatis的逆向工程能自动帮开发者生成数据库表对应的 pojo实体文件,自动生成映射文件
自定生成表的各种(CRUD)的sql语句, 但是只能做单表操作,联合查询还得开发者自己动
使用逆向工程得先在Eclipse安装逆向工程的插件
 
配置生成文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="context1">
<!-- 注释构建 -->
<commentGenerator>
<!-- 去掉所有的注释 -->
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
</commentGenerator>
 
<!-- 数据库四要素 -->
<jdbcConnection connectionURL="jdbc:mysql://localhost:3306/mybatis"
driverClass="com.mysql.jdbc.Driver"
password="admin"
userId="root" />
<!-- 实体类 : pojo
targetPackage : 实体类生成后存放的包
targetProject : 存放的目录一般都放在 src下面
-->
<javaModelGenerator targetPackage="cn.zj.mybatis.pojo" targetProject="mybatis-generator/src" />
<!-- 映射文件 -->
<sqlMapGenerator targetPackage="cn.zj.mybatis.mapper" targetProject="mybatis-generator/src" />
<!-- 操作接口
type 生成映射的形式
ANNOTATEDMAPPER : 纯注解的,没有xml映射
XMLMAPPER : 生成的有xml映射文件
-->
<javaClientGenerator targetPackage="cn.zj.mybatis.mapper" targetProject="mybatis-generator/src" type="XMLMAPPER" />
 
<!-- 要生成对应表的配置
tableName : 数据库表名
//如果下面全部是true,mybatis直接可以使用纯面向对象开发
enableCountByExample : 是否生成查询总数的 Example
enableDeleteByExample : 是否生成删除的 Example
enableSelectByExample : 是否生成查询集合的 Example
enableUpdateByExample : 是否生成修改的 Example
-->
<table tableName="user" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>
<table tableName="employee" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>
<table tableName="department" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>
</context>
</generatorConfiguration>
 
 
开始逆向工程
选中 generatorConfig.xml 逆向工程配置文件,点击鼠标右键

逆向功能的缺点
逆向功能不能逆向多表,只能逆向单表操作,多表之间有外键对应java关联关系没办法映射,需要开发者手动编写对应代码
 

MyBatis_02 框架的更多相关文章

  1. 避免重复造轮子的UI自动化测试框架开发

    一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...

  2. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  3. 旺财速啃H5框架之Bootstrap(五)

    在上一篇<<旺财速啃H5框架之Bootstrap(四)>>做了基本的框架,<<旺财速啃H5框架之Bootstrap(二)>>篇里也大体认识了bootst ...

  4. Angular企业级开发(5)-项目框架搭建

    1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...

  5. Scrapy框架爬虫初探——中关村在线手机参数数据爬取

    关于Scrapy如何安装部署的文章已经相当多了,但是网上实战的例子还不是很多,近来正好在学习该爬虫框架,就简单写了个Spider Demo来实践.作为硬件数码控,我选择了经常光顾的中关村在线的手机页面 ...

  6. 制作类似ThinkPHP框架中的PATHINFO模式功能

    一.PATHINFO功能简述 搞PHP的都知道ThinkPHP是一个免费开源的轻量级PHP框架,虽说轻量但它的功能却很强大.这也是我接触学习的第一个框架.TP框架中的URL默认模式即是PathInfo ...

  7. 旺财速啃H5框架之Bootstrap(四)

    上一篇<<旺财速啃H5框架之Bootstrap(三)>>已经把导航做了,接下来搭建内容框架.... 对于不规整的网页,要做成自适应就有点玩大了.... 例如下面这种版式的页面. ...

  8. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  9. Hibernatel框架关联映射

    Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...

随机推荐

  1. 关于JAVA线程池-ThreadPoolExecutor

    1. 源码翻译 /* * * * * * * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Grou ...

  2. HBase-集群安装

    需要先启动 HDFS 集群和 ZooKeeper 集群. Hadoop 集群安装:https://www.cnblogs.com/jhxxb/p/10629796.html ZooKeeper 集群安 ...

  3. oracle中的trigger

    https://blog.csdn.net/indexman/article/details/8023740/ https://www.cnblogs.com/sharpest/p/7764660.h ...

  4. Oralce JDBC jar包下载

    下载地址:https://pan.baidu.com/s/1sU7gu4biigEAw-3Bu7yIOA 下载包中包括以下文件: ojdbc5.jarojdbc5dms.jarojdbc5dms_g. ...

  5. Elasticsearch .net 记录-1

    简介 ElasticSearch是一个开源的分布式搜索引擎,具备高可靠性,支持非常多的企业级搜索用例.像Solr4一样,是基于Lucene构建的.支持时间时间索引和全文检索.官网:http://www ...

  6. QML使用MouseArea

    1.普通使用 MouseArea { anchors.fill: parent hoverEnabled: true//为true才会触发进入信号 onClicked: { } onEntered: ...

  7. 三个线程abc顺序执行

    1.使用synchronized悲观锁(秋招阿里的一个笔试题,应该写的比较复杂,然后就没有然后了o(╥﹏╥)o) public class ThreadThreadp { private int fl ...

  8. PAT 甲级 1036 Boys vs Girls (25 分)(简单题)

    1036 Boys vs Girls (25 分)   This time you are asked to tell the difference between the lowest grade ...

  9. spark osx:WARN NativeCodeLoader:62 - Unable to load native-hadoop library for your platform

    spark-env.sh文件中增加,确保${HADOOP_HOME}/lib/native目录下有libhadoop.so文件 export JAVA_LIBRARY_PATH=${HADOOP_HO ...

  10. 【POJ - 2010】Moo University - Financial Aid(优先队列)

    Moo University - Financial Aid Descriptions 奶牛大学:奶大招生,从C头奶牛中招收N(N为奇数)头.它们分别得分score_i,需要资助学费aid_i.希望新 ...