Hibernate:全自动
黑箱操作,无法优化SQL 需要学HQL
mybatis:半自动框架 轻量级的框架
自己写SQL 可以优化
SQL与JAVA编码分离 配置文件配置即可
<configuration>
<environments default=\"a\">
<environment id=\"a\">
<transactionManager type=\"JDBC\"></transactionManager>
<dataSource type=\"POOLED\">
<property name=\"driver\" value=\"com.mysql.jdbc.Driver\" />
<property name=\"url\" value=\"jdbc:mysql://localhost:3306/test\" />
<property name=\"username\" value=\"root\" />
<property name=\"password\" value=\"7777777\" />
</dataSource>
</environment>
</environments>
<!-- 将映射文件 注册到全局配置文件中 -->
<mappers>
<mapper resource=\"EmployeeMapper. \"/>
</mappers>
</configuration>
-------------------
<mapper namespace=\"com.mybatis.pojo.EmployeeMapper\">
<!-- #{id}从传递过来的参数中取id值-->
<select id=\"selectEmp\" resultType=\"com.mybatis.pojo.Employee\">
SELECT id,last_name lastName,email,gender FROM employee WHERE id= #{id}
</select>
</mapper>
-----------------------
String resource = \"mybatis-config. \";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
//第一个参数 唯一标识
Employee employee = sqlSession.selectOne(\"com.mybatis.pojo.EmployeeMapper.selectEmp\", 1);
System.out.println(employee);
sqlSession.close();
---------------------------
新版本方法:
namespace 指定为接口的全类名<mapper namespace=\"com.mybatis.mapper.EmployeeMapper\">
将select的id改为方法的名称<select id=\"getEmpById\"
String resource = \"mybatis-config. \";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
// //第一个参数 唯一标识
// Employee employee = sqlSession.selectOne(\"com.mybatis.pojo.EmployeeMapper.selectEmp\", 1);
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = mapper.getEmpById(1);
System.out.println(employee);
sqlSession.close();
原理:mybatis会为接口代理 增强并实现这个接口 对应的操作数据库的方法
------------------------------
注意:mybatis是非线程安全的 定义私有变量属性 private SqlSession sqlSession
每次使用都要获取新的对象
------------------
开启驼峰命名:
<settings>
<setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>
</settings>
如果属性名和数据库字段名就是不同:
自定义映射:<Mapper><resultMap type=\"对象类型\" id=\"\"><result property=\"属性名\" column=\"字段名\">
使用 将resultType 替换为 resultMap
<resultMap id=\"resultmap\" type=\"com.mybatis.pojo.Employee\" autoMapping=\"true\">
<result property=\"empMail\" column=\"email\" />
<result property=\"dept.deptId\" column=\"deptId\"/>
</resultMap>
使用association 来设置级联属性
--------------------------------------
给java类型取别名
<typeAliases>
<typeAlias type=\"com.mybatis.pojo.Employee\" alias=\"Employee\"/>
</typeAliases>
<select id=\"getEmpById\" resultType=\"Employee\">
为某个包下的所有类取别名 默认是类名首字母小写
<typeAliases>
<package name=\"com.mybatis.pojo\"></package>
</typeAliases>
<select id=\"getEmpById\" resultType=\"employee\">
SELECT * FROM employee WHERE id= #{id}
</select>
但是会存在重名冲突
可以使用注解 @Alias(\"\")来避免 但是要和package配合使用
注意:不要和mybatis 已经定义好的重合、
建议写全类名 结构清晰
-------------------------------------------------
别名处理器: TypeHandler<String> 来自定义java的类型和数据库的转换
并使用@mappedJdbcTypes(JdbcType.VARCHAR)
在全局配置文件中使用<typeHandler handler=\"全类名\">进行配置
-------------------------------------------------
mybatis 支持多环境配置
<environment id=\"development\">
-------------------------------
多数据库支持
在全局配置文件中:
<data IdProvider type=\"DB_VENDOR\">
<!-- 为不同的数据库厂商取别名-->
<property name=\"MySQL\" value=\"mysql\"/>
<property name=\"SQL Server\" value=\"sql server\"/>
</data IdProvider>
在映射文件中:
告诉mybatis是哪个厂商
<select id=\"getEmpById\" resultType=\"com.mybatis.pojo.Employee\" data Id=\"mysql\">
注意:有顺序
-------------------------------------------------
mapmapper 标签:
resource:引用类路径下的sql映射文件
url:引用磁盘下的映射文件
class:引用注册接口 接口名必须和映射文件名同名并且在同一个包里
---------------------------
sql写在方法上
@Select(\"select * from employee where id=#{id}\")
public interface EmployeeMapper {
@Select(\"select * from employee where id=#{id}\")
public Employee getEmpById(Integer id);
}
<mappers>
<mapper class=\"com.mybatis.mapper.EmployeeMapper\"/>
</mappers>
-----------------------------------
注意:sqlSession要手动提交 可以使用可以自动提交的sqlSession的构造方法
执行完后 将自动生成的主键 自动装配给bean的属性
<insert id=\"addEmp\" parameterType=\"com.mybatis.pojo.Employee\"
useGeneratedKeys=\"true\" keyProperty=\"id\">
insert into employee(lase_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>
public void addEmp(Employee employee);
-----------------------------------
#{} 从map中取值 一个参数时#{随便都可以} 多个参数时key为param1...param2...
获取时#{param1},#{param2}
解决方法:使用注解指定key值 public Employee getEmpById(@Param(\"id\") Integer id);
获取时#{id}
可以传对象 从对象中取属性 #{对象中的属性名} 它会自动识别
使用Map 作为参数 #{key} 就是取出map中对应key的value
推荐 别写一个数据传输对象 TO
如果是Collection (List) 特殊处理 把传入的list封装在map中 Collection 的key就是collection
精确 List key就是list #{list[0]}
# 是预编译的形式PreparedStatement 而$取出的值直接拼装在sql语句中
# 可以防止sql注入
返回值类型为List时 :配置对应sql映射时 resultType并不是list 而是list当中的泛型
返回值为map 在接口对应方法上加@MapKey(\"对象属性名 主键\") resultType=\"对象\"
自定义结果集映射
resultMap:
<!-- type为要为哪个对象自定义映射-->
<resultMap id=\"MyEmp\" type=\"com.mybatis.pojo.Employee\">
<!-- 指定主键列的封装规则-->
<!-- 指定哪一列 对应的java属性-->
<id column=\"id\" property=\"id\"/>
<!-- 定义普通列-->
<result column=\"last_name\" property=\"lastName\"/>
<!-- 其他不指定的列会自动封装-->
<result column=\"email\" property=\"email\"/>
<result property=\"gender\" column=\"gender\"/>
</resultMap>
<!-- #{id}从传递过来的参数中取id值-->
<select id=\"getEmpById\" resultMap=\"MyEmp\">
SELECT * FROM employee WHERE id= #{id}
</select>
----------------------
关联查询:
resultMap:
查出Employee时查出部门的信息
方法一:
<resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
<id column=\"id\" property=\"id\"/>
<result property=\"lastName\" column=\"last_name\"/>
<result property=\"email\" column=\"email\"/>
<result column=\"gender\" property=\"gender\"/>
<result property=\"dept.id\" column=\"did\"/>
<result column=\"dept_name\" property=\"dept.departmentName\"/>
</resultMap>
<select id=\"getEmpAndDept\" resultMap=\"EmpAndDept\">
select e.id id,e.last_name last_name,e.email email,e.gender gender,e.d_id d_id,d.id did,d.dept_name dept_name from employee e,dept d where e.d_id = d.id AND e.id=#{id}
</select>
方法二:
<resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
<id column=\"id\" property=\"id\"/>
<result property=\"lastName\" column=\"last_name\"/>
<result property=\"email\" column=\"email\"/>
<result column=\"gender\" property=\"gender\"/>
<association property=\"dept\" javaType=\"com.mybatis.pojo.Department\">
<id column=\"did\" property=\"id\"/>
<result property=\"departmentName\" column=\"dept_name\"/>
</association>
<!--<result property=\"dept.id\" column=\"did\"/>-->
<!--<result column=\"dept_name\" property=\"dept.departmentName\"/>-->
</resultMap>
-------------------------------------
association 分步查询:
<resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
<id column=\"id\" property=\"id\"/>
<result property=\"lastName\" column=\"last_name\"/>
<result property=\"email\" column=\"email\"/>
<result column=\"gender\" property=\"gender\"/>
<!--<association property=\"dept\" javaType=\"com.mybatis.pojo.Department\">-->
<!--<id column=\"did\" property=\"id\"/>-->
<!--<result property=\"departmentName\" column=\"dept_name\"/>-->
<!--</association>-->
<!--<result property=\"dept.id\" column=\"did\"/>-->
<!--<result column=\"dept_name\" property=\"dept.departmentName\"/>-->
<!--使用分步查询 查员工后 会有did 根据did查部门 column 指定将那一列的值传给这个方法-->
<association property=\"dept\" select=\"com.mybatis.mapper.DepartmentMapper.getDepartmentById\" column=\"d_id\">
</association>
</resultMap>
<select id=\"getEmpAndDept\" resultMap=\"EmpAndDept\">
select * from employee where id=#{id}
</select>
------------------------
<mapper namespace=\"com.mybatis.mapper.DepartmentMapper\">
<resultMap id=\"department\" type=\"com.mybatis.pojo.Department\">
<id column=\"id\" property=\"id\"></id>
<result property=\"departmentName\" column=\"dept_name\"/>
</resultMap>
<select id=\"getDepartmentById\" resultMap=\"department\">
select * from dept where id=#{id}
</select>
</mapper>
------------------------------
分布查询延迟加载:分步查询基础上加两个配置
<settings>
<setting name=\"lazyLoadingEnabled\" value=\"true\"/>
<setting name=\"aggressiveLazyLoading\" value=\"false\"/>
</settings>
-------------------------
一对多:
collection:
<resultMap id=\"OneToMany\" type=\"com.mybatis.pojo.Department\">
<id column=\"did\" property=\"id\"></id>
<result property=\"departmentName\" column=\"dept_name\"/>
<!--定义集合类型属性
ofType 集合里元素的类型-->
<collection property=\"emps\" ofType=\"com.mybatis.pojo.Employee\">
<id column=\"eid\" property=\"id\"/>
<result property=\"lastName\" column=\"last_name\"/>
<result column=\"email\" property=\"email\"/>
<result property=\"gender\" column=\"gender\"/>
</collection>
</resultMap>
<select id=\"getDepartmentByIdPlus\" resultMap=\"OneToMany\">
select d.id did,d.dept_name dept_name,e.id eid,e.last_name last_name,e.email email,e.gender gender from dept d left join employee e
on d.id = e.id
where d.id=#{id}
</select>
---------------------
collection 分段查询
<resultMap id=\"OneToMany\" type=\"com.mybatis.pojo.Department\">
<id column=\"did\" property=\"id\"></id>
<result property=\"departmentName\" column=\"dept_name\"/>
<!--定义集合类型属性
ofType 集合里元素的类型-->
<!--<collection property=\"emps\" ofType=\"com.mybatis.pojo.Employee\">-->
<!--<id column=\"eid\" property=\"id\"/>-->
<!--<result property=\"lastName\" column=\"last_name\"/>-->
<!--<result column=\"email\" property=\"email\"/>-->
<!--<result property=\"gender\" column=\"gender\"/>-->
<!--</collection>-->
<collection property=\"emps\" select=\"com.mybatis.mapper.EmployeeMapper.getEmployeeByDeptId\" column=\"did\">
</collection>
</resultMap>
<select id=\"getDepartmentByIdPlus\" resultMap=\"OneToMany\">
select d.id did,d.dept_name dept_name from dept d
where d.id=#{id}
</select>
传递一个值用 column 传递多个值 封装map传递:column=\"{key1=column1,...}\"
column=\"{deptId=did} fetchType=\"lazy\"懒加载
-----------------------------
鉴别器:
<resultMap id=\"MyEmpDiscriminator\" type=\"com.mybatis.pojo.Employee\">
<id column=\"id\" property=\"id\"/>
<result property=\"lastName\" column=\"last_name\"/>
<result property=\"email\" column=\"email\"/>
<result column=\"gender\" property=\"gender\"/>
<!--column 指定要判断哪列 javaType 就是列值对应的类型-->
<discriminator javaType=\"string\" column=\"gender\">
<!--0女生 1男生 resultType 指定封装的结果类型-->
<case value=\"0\" resultType=\"com.mybatis.pojo.Employee\">
<association property=\"dept\" select=\"com.mybatis.mapper.DepartmentMapper.getDepartmentById\" column=\"d_id\">
</association>
</case>
<case value=\"1\"></case>
</discriminator>
</resultMap>
------------------------
动态SQL
if:
<select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
select * from employee
where
<if test=\"id != null\">
id=#{id}
</if>
<if test=\"lastName != null and lastName != \'\'\">
and last_name like #{lastName}
</if>
<if test=\"email!=null and email.trim()!=\'\'\">
and email=#{email}
</if>
<if test=\"gender!=null\">
and gender=#{gender}
</if>
</select>
如果没有id就会出错 会多出一个and
解决方案:
1、给where 后面加 1=1
2、使用where标签 只会去掉第一个多出来的and
3、使用trim标签
<trim prefix=\"\" prefixOverrides=\"\" suffix=\"\" suffixOverrides=\"\">
prefix给拼完后的字符串加一个前缀
prefixOverrides前缀覆盖
suffix给字符串加一个后缀
suffixOverides后缀覆盖
<select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
select * from employee
--
<trim prefix=\"where\" prefixOverrides=\"and\" suffixOverrides=\"and\">
<if test=\"id != null\">
id=#{id}
</if>
<if test=\"lastName != null and lastName != \'\'\">
and last_name like #{lastName}
</if>
<if test=\"email!=null and email.trim()!=\'\'\">
and email=#{email}
</if>
<if test=\"gender!=null\">
and gender=#{gender}
</if>
</trim>
</select>
-------------------
choose when otherwise标签:
<select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
select * from employee
<where>
<choose>
<when test=\"id != null\">
id=#{id}
</when>
<when test=\"lastName != null and lastName != \'\'\">
last_name like #{lastName}
</when>
<when test=\"email!=null and email.trim()!=\'\'\">
email=#{email}
</when>
<otherwise>
gender=#{gender}
</otherwise>
</choose>
</where>
</select>
---------------------------
set标签
<update id=\"updateEmp\">
update employee
<set>
<if test=\"lastName!=null\">
last_name=#{lastName},
</if>
<if test=\"email!=null\">
email=#{email},
</if>
</set>
where id=#{id}
</update>
------------------
<update id=\"updateEmp\">
update employee
<trim prefix=\"set\" suffixOverrides=\",\">
<if test=\"lastName!=null\">
last_name=#{lastName},
</if>
<if test=\"email!=null\">
email=#{email},
</if>
</trim>
where id=#{id}
</update>
----------------------
foreach 标签
select * from employee
<foreach collection=\"\" item=\"\" open=\"where id in (\" close=\")\" separator=\",\" >
</foreach>
---------------
foreach 用于批量插入 遍历对象 对每一个item=\"emp\" #{emp.lastName}取值
-------------------------
两个内置参数:不只有方法传递过来的参数 它还有内置的参数
:_parameter代表整个参数(单个时就是这个参数,多个时就是这个map)
_data Id代表如果配置了Data IdProvider标签 代表它的别名
在select标签中实验if标签判断 _data Id 调用不同的语句 来实现多数据库
-----------------------
数据绑定 <bind name=\"_lastName\" value=\"\'%\'+lastName+\'%\'\"> 后就可以使用#{_lastName}实现传参不用传%
抽取sql片段:
<!--抽取可重用的sql片段-->
<sql id=\"insertColumn\">
id,last_name,email,#{test}
</sql>
<insert id=\"\">
insert into employee(
<include refid=\"insertColumn\">
<property name=\"test\" value=\"abc\"></property>
</include>
)
values (1,\"tt\",\"tt@qq.com\")
</insert>
---------------------------
缓存:一级缓存:本地缓存
二级缓存:全局缓存<setting name=\"cacheEnabled\" value=\"true\"/>
<mapper namespace=\"com.mybatis.mapper.EmployeeMapper\">
<!--使用二级缓存 POJO需要实现序列化接口-->
<cache type=\"自定义缓存的全类名 实现Cache接口即可 例如ehcache的全类名\" blocking=\" \" eviction=\"缓存的回收策略\" flushInterval=\"缓存刷新间隔\" readOnly=\"是否只读\" size=\"存放多少元素\"/>
<select useCache=\"true\">
<mapper/>
session关闭后 一级缓存的数据放入二级缓存 其他session可以获取 不要发语句
继续阅读与本文标签相同的文章
上一篇 :
LeetCode40-组合总数II
-
地球如果流浪,大数据究竟能做什么?
2026-05-18栏目: 教程
-
网站漏洞测试 sql注入攻击代码的审计与检测
2026-05-18栏目: 教程
-
【DockerCon2017技术解读】使用Moby工具和Linuxkit定制容器系统
2026-05-18栏目: 教程
-
如何设置开机启动holer
2026-05-18栏目: 教程
-
【阿里云新品发布·周刊】第25期:硬核!阿里云新品动态一手掌握
2026-05-18栏目: 教程
