企业网站和信息化建设金蝶,企业网站推广推广阶段,做网站基本步骤,企查查怎么精准找客户MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程#xff08;增删改#xff09;2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架
文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程增删改2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体类类型的参数5 使用 Param 注解的参数三 自定义查询结果 resultMap1 处理表的字段和属性的映射关系2 处理多对一关系3 处理一对多关系四 动态 SQL1 if 标签2 where 标签3 trim 标签4 choose, when, otherwise 标签5 foreach 标签6 sql 标签五 MyBatis 缓存1 一级缓存2 二级缓存3 查询顺序六 逆向工程一 基于配置文件的 MyBatis 搭建
1 搭建过程增删改
配置过程核心配置文件通过配置 mappers 找到映射文件映射文件通过全类名和方法名定位到具体的接口和方法
创建 maven 工程引入依赖在 src/main/resources 目录下创建核心配置文件 mybatis-config.xml核心配置文件主要用于配置连接数据库的环境以及 MyBatis 的全局配置信息整合 Spring 之后配置文件可以省略
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!--设置连接数据库的环境--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valuecom.mysql.jdbc.Driver/property nameurlvaluejdbc:mysql://localhost:3306/learn/property nameusername valueroot/property namepassword value123456//dataSource/environment/environments!--引入UserMapper.xml的映射文件--mappersmapper resourcemappers/UserMapper.xml/!--其他映射文件...--/mappers
/configuration创建实体类型以及数据库中对应的表创建 mapper 接口mapper 接口相当于 dao但是 mapper 仅仅是接口不需要提供实现类具体的 SQL 命令写在 映射文件 xxxMapper.xml 中xxx和类名保持一致创建 MyBatis 映射文件在对应的位置标注全类名和方法两个一致mapper接口的全类名和映射文件的 namespace 保持一致 mapper 接口中方法的方法名和映射文件中编写 SQL 的标签的 id 属性保持一致
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--对应的Mapper的全类名--
mapper namespacehello.mapper.UserMapper!--对应的方法--insert idinsertUserinsert into user values (null, 伍佰, 500, 50, 男, 500gmail.com)/insert
/mapper测试 Testpublic void helloTest() throws IOException {//读取MyBatis的核心配置文件InputStream is Resources.getResourceAsStream(mybatis-config.xml);//创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory生产SqlSession对象SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(is);//创建SqlSession对象此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务//SqlSession sqlSession sqlSessionFactory.openSession();//创建SqlSession对象此时通过SqlSession对象所操作的sql都会自动提交SqlSession sqlSession sqlSessionFactory.openSession(true);//通过代理模式创建UserMapper接口的代理实现类对象UserMapper userMapper sqlSession.getMapper(UserMapper.class);//调用UserMapper接口中的方法就可以根据UserMapper的全类名匹配元素文件通过调用的方法名匹配映射文件中的SQL标签并执行标签中的SQL语句int result userMapper.insertUser();}2 查询操作
映射文件 UserMapper.xml 中为了设置实体类和数据库表的映射查询功能的标签必须指定 resultType自动映射用于属性名和表中字段名一致的情况 或 resultMap自定义映射用于一对多 / 多对一 / 字段名和属性名不一致 的情况 属性
查询单个对象单个对象也可以使用 List 接口定义方法User getUserById();映射文件select idgetUserById resultTypehello.pojo.Userselect * from user where id 1/select查询多个对象 接口定义方法ListUser getAllUser();映射文件select idgetAllUser resultTypehello.pojo.Userselect * from user/select3 特殊操作
模糊查询
select idfuzzy resultTypeUserselect * from user where username like %#{name}%
/select批量删除不能使用 #{ } 是因为它会自动添加单引号
!--int deleteMore(Param(ids) String ids);--
delete idbatchDeletedelete from user where id in (${ids}) !--示例delete from user where id in (1, 2, 3)--
/delete二 MyBatis 获取参数值的方式
#{ } 对应占位符赋值${ } 对应字符串拼接外侧需要加单引号不关心接口中方法的形参命名
1 单个字面量类型的参数
可以以任意的名称获取参数的值不在乎接口中的方法形参的名字但最好见名知意
接口方法
public interface ParamMapper {// 根据用户名查询用户信息User getUserByName(String username);
}映射文件
select idgetUserByName resultTypeparam.pojo.Userselect * from user where username #{notmatters}select * from user where username ${notmatters} !--等价--
/select2 多个字面量类型的参数
接口中的方法参数为多个MyBatis 会自动将这些参数放在一个 map 集合中以arg0, arg1…为键以参数为值 或 以 param1, param2…为键以参数为值通过键访问参数
接口方法
public interface ParamMapper {// 验证登录User checkLogin(String username, String password);
}映射文件
select idcheckLogin resultTypeparam.pojo.Userselect * from user where username #{arg0} and password #{arg1}select * from user where username #{param1} and password #{param2} !--等价--
/select3 Map 类型的参数
方法参数为一个 Map 时使用自定义的 key 访问 value
接口方法
public interface ParamMapper {// 验证登录 参数为MapUser checkLoginByMap(MapString, Object mapParam);
}映射文件
select idcheckLoginByMap resultTypeparam.pojo.Userselect * from user where username #{usernameKey} and password #{passwordKey}
/select测试
...
Map param new HashMapString, Object();
param.put(usernameKey, 伍佰);
param.put(passwordKey, 500);
userMapper.checkLoginByMap(param);4 实体类类型的参数
通过访问实体类对象中的属性名获取属性值
接口方法
public interface ParamMapper {// 添加用户int insertUser(User paramUser);
}映射文件
insert idinsertUserinsert into user values (#{id}, #{username}, #{password}, #{age}, #{sex}, #{email})
/insert5 使用 Param 注解的参数
可以替代情况1和2作用是指定 map 的键通过 Param 注解标识接口中的方法参数会将这些参数放在 map 集合中以 Param 注解的 value 属性值为键以参数为值替换键 arg0, arg1…
接口方法
public interface ParamMapper {// 验证登录 参数使用注解User checkLoginByAnnotation(Param(u) String username, Param(p) String password);
}映射文件
select idcheckLoginByAnnotation resultTypeparam.pojo.Userselect * from user where username #{u} and password #{p}
/select三 自定义查询结果 resultMap resultMap设置自定义映射 包含属性 id表示自定义映射的唯一标识 type查询的数据要映射的实体类的类型 resultMap 的子标签 id设置主键的映射关系 result设置普通字段的映射关系 association设置多对一的映射关系 collection设置一对多的映射关系 每个标签包含属性 property设置映射关系中实体类中的属性名 column设置映射关系中表中的字段名
1 处理表的字段和属性的映射关系
若字段名和实体类中的属性名不一致则可以通过 resultMap 设置自定义映射所有映射需要全部设置略有臃肿可以使用别名的方式只对不一致的表字段起别名 select id, user_name userName, password, age, sex from user where user_name like %#{mohu}%
resultMap iduserMap typeparam.pojo.Userid propertyid columnid/idresult propertyuserName columnuser_name/resultresult propertypassword columnpassword/resultresult propertyage columnage/resultresult propertysex columnsex/result
/resultMapselect idtestFuzzy resultMapuserMapselect * from user where user_name like %#{fuzzy}%
/select2 处理多对一关系
示例根据员工id查询员工信息和部门信息
POJO省略 Lombok 注解
public class Employee {private Integer eid;private String ename;private Department department;
}public class Department {private Integer did;private String dname;
}接口方法
public interface ResultMapMapper {Employee getEmpAndDept(Param(eid) Integer eid);}映射文件使用 association 子标签后左表 employee 可以访问属性 didassociation 标签需要指明属性 javaType
mapper namespaceglad.mapper.ResultMapMapperresultMap idmyResultMap typeglad.pojo.Employeeid propertyeid columneid/idresult propertyename columnename/resultassociation propertydepartment javaTypeglad.pojo.Departmentid propertydid columndid/idresult propertydname columndname/result/association/resultMapselect idgetEmpAndDept resultMapmyResultMap!--使用 association 后employee 可以访问属性 did--select * from employee left join department on employee.did department.did where employee.eid #{eid}/select
/mapper查询结果
3 处理一对多关系
示例根据部门id查询其员工信息
POJO省略 Lombok 注解
public class Employee {private Integer eid;private String ename;private Integer did;
}public class Department {private Integer did;private String dname;ListEmployee emps;
}接口方法
public interface ResultMapMapper {Deptartment getDeptAndEmp(Param(did) Integer did);}映射文件使用 collection 标签声明类的 List 属性并设置标签的 ofType 属性代表容器内元素的属性
mapper namespaceglad.mapper.ResultMapMapperresultMap idmyResultMap typeglad.pojo.Departmentid propertydid columndid/idresult propertydname columndname/resultcollection propertyemps ofTypeglad.pojo.Employeeid propertyeid columneid/idresult propertyename columnename/result/collection/resultMapselect idgetDeptAndEmp resultMapmyResultMapselect * from department left join employee on department.did employee.did where department.did #{did}/select
/mapper四 动态 SQL
1 if 标签
满足指定条件时才会将 if 标签中的 SQL 加入
POJO省略 Lombok 注解和表中的属性名以 X 区分注意在映射文件的各处访问的是表还是传入的参数
public class User {private Integer idX;private String usernameX;private String passwordX;private Integer ageX;private String sexX;private String emailX;
}接口方法
public interface DynamicMapper {// 根据任意信息查询ListUser getInfo(User user);}映射文件 数据库表的字段和类的属性名不一致时使用 resultMap否则查询结果一直为 null 为了保证格式正确需要在 where 后加一个恒成立条件
mapper namespacedynamic.mapper.DynamicMapperresultMap idmyResultMap typedynamic.pojo.Userid propertyidX columnid/idresult propertyusernameX columnusername/resultresult propertypasswordX columnpassword/resultresult propertyageX columnage/resultresult propertysexX columnsex/resultresult propertyemailX columnemail/result/resultMapselect idgetInfo resultMapmyResultMapselect * from user where 1 1if testidX ! and idX ! nulland id #{idX}/ifif testusernameX ! and usernameX ! nulland username #{usernameX}/ifif testpasswordX ! and passwordX ! nulland password #{passwordX}/ifif testageX ! and ageX ! nulland age #{ageX}/ifif testsexX ! and sexX ! nulland sex #{sexX}/ifif testemailX ! null and emailX !and email #{emailX}/if/select
/mapper2 where 标签
一般和 if 标签结合使用 若 where 标签中的 if 子标签条件都不满足则 where 标签没有任何功能即不会添加 where 关键字 若 where 标签中的 if 子标签条件满足则 where 标签会自动添加 where 关键字并将条件最前方多余的 and 去掉
select idgetEmpListByMoreTJ2 resultTypeEmpselect * from t_empwhereif testename ! and ename ! nullename #{ename}/ifif testage ! and age ! nulland age #{age}/ifif testsex ! and sex ! nulland sex #{sex}/if/where
/select3 trim 标签
trim 用于去掉或添加标签中的内容
属性作用prefix在 trim 标签中的内容的前面添加某些内容prefixOverrides在 trim 标签中的内容的前面去掉某些内容suffix在 trim 标签中的内容的后面添加某些内容suffixOverrides在 trim 标签中的内容的后面去掉某些内容
映射文件
select idgetEmpListByMoreTJ resultTypeEmpselect * from t_emp!--在以下部分的开头添加where末尾删去and--trim prefixwhere suffixOverridesandif testename ! and ename ! nullename #{ename} and/ifif testage ! and age ! nullage #{age} and/ifif testsex ! and sex ! nullsex #{sex}/if/trim
/select4 choose, when, otherwise 标签
choose 是 when 和 otherwise 的父标签组合使用的效果相当于 Java 的 if, else if, else
映射文件
!--ListEmp getEmpListByChoose(Emp emp);--
select idgetEmpListByChoose resultTypeEmpselect * from t_empwherechoosewhen testename ! and ename ! nullename #{ename}/whenwhen testage ! and age ! nullage #{age}/whenwhen testsex ! and sex ! nullsex #{sex}/whenwhen testemail ! and email ! nullemail #{email}/when/choose/where
/select5 foreach 标签
用于执行批量操作
属性作用collection设置要循环的数组或集合item表示集合或数组中的每一个数据separator设置元素之间的分隔符open设置 foreach 标签中的内容的开始符close设置 foreach 标签中的内容的结束符
映射文件
!--int insertMoreEmp(Param(emps) ListEmp emps);--
insert idinsertMoreEmpinsert into t_emp valuesforeach collectionemps itememp separator,(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)/foreach
/insert!--int deleteMoreByArray(Param(eids) int[] eids);--
delete iddeleteMoreByArraydelete from t_emp where eid inforeach collectioneids itemeid separator, open( close)#{eid}/foreach
/delete6 sql 标签
提取 SQL 语句的公共部分
sql idempColumnseid, ename, age, sex, did
/sql引用
select include refidempColumns/include from t_emp五 MyBatis 缓存
1 一级缓存
一级缓存是 SqlSession 级别的通过同一个 SqlSession 查询的数据会被缓存下次查询相同的数据就会从缓存中直接获取不会从数据库重新访问使一级缓存失效的四种情况 不同的 SqlSession 对应不同的一级缓存同一个 SqlSession 但是查询条件不同同一个 SqlSession 两次查询期间执行了任何一次增删改操作同一个 SqlSession 两次查询期间手动清空了缓存
2 二级缓存
二级缓存是 SqlSessionFactory 级别通过同一个 SqlSessionFactory 创建的 SqlSession 查询的结果会被缓存此后若再次执行相同的查询语句结果就会从缓存中获取使二级缓存失效的情况两次查询之间执行了任意的增删改会使一级和二级缓存同时失效开启二级缓存的步骤 在核心配置文件中设置全局配置属性cacheEnabled“true”默认为true不需要设置在映射文件中设置标签 cache二级缓存必须在 SqlSession 关闭或提交之后有效一个 SqlSession 写入二级缓存当第一个 SqlSession 关闭或提交后供相同 SqlSessionFactory 创建的另一个 SqlSession 使用查询的数据所转换的实体类类型必须实现序列化的接口 Serializable
3 查询顺序
先查询二级缓存因为二级缓存中可能会有其他程序已经查出来的数据可以拿来直接使用。如果二级缓存没有命中再查询一级缓存如果一级缓存也没有命中则查询数据库SqlSession 关闭之后一级缓存中的数据会写入二级缓存 六 逆向工程
逆向工程先创建数据库表由框架负责根据数据库表反向生成 Java 实体类、Mapper 接口、Mapper 映射文件
引入依赖、配置核心配置文件 !-- 控制Maven在构建过程中相关配置 --build!-- 构建过程中用到的插件 --plugins!-- 具体插件逆向工程的操作是以构建过程中插件形式出现的 --plugingroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-maven-plugin/artifactIdversion1.4.0/version!-- 插件的依赖 --dependencies!-- 逆向工程的核心依赖 --dependencygroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-core/artifactIdversion1.4.0/version/dependency!-- 数据库连接池 --dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.2/version/dependency!-- MySQL驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.20/version/dependency/dependencies/plugin/plugins/build创建逆向工程的配置文件必须命名为 generatorConfig.xml
?xml version1.0 encodingUTF-8?
!DOCTYPE generatorConfigurationPUBLIC -//mybatis.org//DTD MyBatis Generator Configuration 1.0//ENhttp://mybatis.org/dtd/mybatis-generator-config_1_0.dtdgeneratorConfiguration!--targetRuntime: 执行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUDMyBatis3: 生成带条件的CRUD--context idDB2Tables targetRuntimeMyBatis3!-- 数据库的连接信息 --jdbcConnection driverClasscom.mysql.cj.jdbc.DriverconnectionURLjdbc:mysql://localhost:3306/learn?serverTimezoneUTCuserIdrootpassword123456/jdbcConnection!-- javaBean的生成策略--javaModelGenerator targetPackagemybatis.beantargetProject.\src\main\javaproperty nameenableSubPackages valuetrue /property nametrimStrings valuetrue //javaModelGenerator!-- SQL映射文件的生成策略 --sqlMapGenerator targetPackagemybatis.mappertargetProject.\src\main\resourcesproperty nameenableSubPackages valuetrue //sqlMapGenerator!-- Mapper接口的生成策略 --javaClientGenerator typeXMLMAPPERtargetPackagemybatis.mapper targetProject.\src\main\javaproperty nameenableSubPackages valuetrue //javaClientGenerator!-- 逆向分析的表 --!-- tableName设置为*号可以对应所有表此时不写domainObjectName --!-- domainObjectName属性指定生成出来的实体类的类名 --table tableNameemployee domainObjectNameEmployee/table tableNamedepartment domainObjectNameDepartment//context
/generatorConfiguration运行插件生成的 xxExample 用于添加约束具体使用方法见4 执行 CRUD
public class MyTest {Testpublic void reverseTest() throws IOException {// ...InputStream is Resources.getResourceAsStream(mybatis-config.xml);SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(is);SqlSession sqlSession sqlSessionFactory.openSession(true);DepartmentMapper departmentMapper sqlSession.getMapper(DepartmentMapper.class);// 使用QBC形式添加条件DepartmentExample departmentExample new DepartmentExample();departmentExample.createCriteria().andDidEqualTo(1).andDnameEqualTo(保卫处);// 将之前添加的条件通过or拼接其他条件departmentExample.or().andDidIsNotNull();// 传入条件执行sqlSystem.out.println(departmentMapper.countByExample(departmentExample));}
}