今日内容
  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. js 根据滚动条加载数据

    很久没记笔记了,最近搞起web开发了 <html> <head> <script src="http://code.jquery.com/jquery-1.7. ...

  2. Java枚举知识点

    近几天从单例模式及阿里开发手册中遇到枚举,之前没怎么关注过. 便学习一下,此次看了多方资料,并写Demo实现,记录下知识点,方便之后巩固. 枚举的两个优点: 1. 保证了类型安全:调用者无法随意传一个 ...

  3. Echarts 常用API之action行为

    一.Echarts中的action echarts中支持的图表行为,通过dispatchAction触发. 1.highlight 高亮指定的数据图形 dispatchAction({ type: ' ...

  4. linux的常见目录

    常见的目录和作用 目录名 目录名的作用 /bin/ 存放系统命令的目录,普通用户和root都使用,不过放在bin/命令下的单用户模式也可执行 /sbin/ 保存于系统环境相关的命令,只有root可以使 ...

  5. Linux 连接memcache 拒绝连接,防火墙关闭,selinux disabled 仍然不行,最后在外站找到原因,为服务器添加memcache访问权限

    最后啊,不行,直接装memcached  https://www.runoob.com/memcached/memcached-install.html 附上连接:https://www.presta ...

  6. wmi 远程访问问题解决

    WMI远程访问问题解决方法 WMI 全称为:Microsoft Windows Management Instrumentation (WMI)  按微软的介绍大致如下:      WMI 是 Mic ...

  7. mac下如何安装python3?

    1. 安装homebrew $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/insta ...

  8. leetcode 127. Word Ladder、126. Word Ladder II

    127. Word Ladder 这道题使用bfs来解决,每次将满足要求的变换单词加入队列中. wordSet用来记录当前词典中的单词,做一个单词变换生成一个新单词,都需要判断这个单词是否在词典中,不 ...

  9. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_20-认证接口开发-接口测试

    测试接口 因为继承了spring  security会拦截这个请求,我们需要写代码 让他对这个认证接口放行 查看代码发现之前已经写过放行的代码了 发现是路径前面少了auth 加断点,测试.申请令牌 r ...

  10. Java Web接入支付宝扫码付款API(使用SDK证书配置properties )

    一.支付宝当面付功能Demo 官方文档https://docs.open.alipay.com/194/106078/ ps:因为沙箱环境一经配置了证书公钥则无法重置 第一步下载项目SKD&D ...