1.半自动与全自动的区别,MyBatis与Hibrnate的区别:
需要手动编写 sql 来完成,称之为半自动 ORM 映射工具。
查询关联对象或者关联集合对向象时,可以根据对象关系模型直接获取,称为orm的全自动。
他们之间的区别在于sql语句是需要手动编写还是自动获取。
Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。
Hibernate属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
1> MyBatis 把 sql 语句从 Java 源程序中独立出来,放在单独的 XML 文件中编写,给程序的
维护带来了很大便利。
2> MyBatis 封装了底层 JDBC API 的调用细节,并能自动将结果集转换成 Java Bean 对象,
大大简化了 Java 数据库编程的重复工作。
3> 因为 MyBatis 需要程序员自己去编写 sql 语句,程序员可以结合数据库自身的特点灵活
控制 sql 语句,因此能够实现比 Hibernate 等全自动 orm 框架更高的查询效率,能够完成复
杂查询。
hibernate和mybatis对比
1相同之处
Hibernate和mybatis都是属于持久层框架(操作数据库的框架).
操作数据库的底层都是使用的JDBC.
并且都是ORM类型的框架.
通过操作对象,映射操作数据库的表。
2不同之处
映射关系不同:
Hibernate:
实体类对象 =对应=> 数据库的表
对象的属性 =对应=> 表的列
MyBatis:
表dao =对应=> 映射文件
表dao中的方法 =对应=> 映射文件中的sql语句
2.了解orm框架。
对象关系映射简称ORM(Object Relational Mapping)框架采用元数据来描述对象与关系映射的细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。简单理解为一种框架的格式。
它是是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。当前ORM框架主要有五种:Hibernate、iBatis、mybatis、JFinal、EclipseLink。
简单来说ORM框架就是连接数据库的桥梁,就是将数据库类型转换成面向对象编程语言的类型,可以理解为“翻译”。
3.动态sql:一对一、一对多、多对多
动态SQL:
sql的内容是变化的, 可以根据条件获取到不同的sql语句。
主要是where部分发生变化。
动态sql的实现, 使用的是mybatis提供的标签。
一对一表查询:
一对一的关系就是:一个商品对应一个商品种类。所以我们创建实体类的时候,可以这么创建:
- public class Goods {
- private int id;
- private int imgId;
- private String name;
- private String content;
- private int status;
- private String createTime;
- private String updateTime;
- private Category category;
-
- }
然后我们在对应的Dao接口方法里定义函数:
- public interface GoodCategoryDao {
- public List
findAllGoodsWithCate() ; - }
书写sql语句:
- <select id="findAllGoodsWithCate" resultMap="GoodsWithCate">
- select a.*,b.category_name from goods a join category b on a.category_id=b.category_id
- </select>
通过category_id 字段相同来建立两个表一一对应的关系。
一对多表查询: 一对多的场景为:一个商品类型对应了多个商品:
所以我们建立实体类可以在商品类型实体类里边添加一个goods集合:
- public class Category {
- private int categoryId;
- private String categoryName;
- private List
goodsList; - }
然后去添加dao接口方法和xml实现方法:
- public interface GoodCategoryDao {
- public List
findAllGoodsWithCate() ; - public List
findAllCateWithGoods() ; - }
Select方法:
- <select id="findAllCateWithGoods" resultMap="CateWithGoods">
- select b.*,a.* from goods a right join category b on a.category_id=b.category_id
- </select>
动态sql拼接:
- <select id="findStudentByCondition" resultType="Student">
- select * from student where 1=1
- <if test="sName!=null">
- and s_name like #{sName}
- </if>
- <if test="sSex!=null">
- and s_sex =#{sSex}
- </if>
-
- </select>
多对多:涉及到三张表如下:
sys_role

sys_user

sys_role_user
通过sys_role_user表查询每个用户的职称
主方法:
- public List<User> list() {
- List<User> userList = userDao.findAll();
- for (User u : userList){
- Long id = u.getId();
-
- List<Role> roleList = roleDao.findById(id);
- u.setRoles(roleList);
- }
- return userList;
- }
dao层 fundAll()
- public List<User> findAll() {
- return jdbcTemplate.query("select * from sys_user", new BeanPropertyRowMapper
(User.class)); - }
dao层 findById(id)
- public List<Role> findById(Long id) {
- List<Role> query = jdbcTemplate.query("select * from sys_user_role ur, sys_role r where ur.roleId = r.id and ur.userId = ?", new BeanPropertyRowMapper<Role>(Role.class), id);
- return query;
- }
查询结果:

4.mybatis中#与$的区别
#占位符:
1> MyBatis处理 #{ } 占位符,使用的 JDBC 对象是PreparedStatement 对象,执行sql语句的效率更高。
2> 使用PreparedStatement 对象,能够避免 sql 注入,使得sql语句的执行更加安全。
3> #{ } 常常作为列值使用,位于sql语句中等号的右侧;#{ } 位置的值与数据类型是相关的。
4> #传入的参数在SQL中显示为字符串(当成一个字符串),会对自动传入的数据加一个双引号。如下:
- select id,name,age from student where id =#{id}
-
- select id,name,age from student where id ="1"
$占位符:
1> MyBatis处理 ${ } 占位符,使用的 JDBC 对象是 Statement 对象,执行sql语句的效率相对于 #{ } 占位符要更低。
2> ${ } 占位符的值,使用的是字符串连接的方式,有 sql 注入的风险,同时也存在代码安全的问题。
3> ${ } 占位符中的数据是原模原样的,不会区分数据类型。
4> ${ } 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用 ${ }。
5>$传入的参数在SqL中直接显示为传入的值。如下:
- select id,name,age from student where id =${id}
-
- select id,name,age from student where id =1
5.MyBatis缓存
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存,默认情况下,只有一级缓存默认开启。二级缓存需要手动开启和配置,他是基于namespace级别的缓存。一级缓存被称为sqlSession级别的缓存, 二级缓存被称为表级缓存。
一级缓存:
MyBatis的一级缓存默认是开启的,它在一个sqlSession会话里面的所有查询操作都会保存到缓存中,一般来说一个请求中的所有增删改查操作都是在同一个sqlSession里面的,所以我们可以认为每个请求都有自己的一级缓存,如果同一个sqlSession会话中2个查询中间有一个 insert 、update或delete 语句,那么之前查询的所有缓存都会清空。
使用MyBatis开启一次和数据库的会话,MyBatis会创建出一个SqlSession对象表示一次数据库会话,在对数据库的一次会话中, 有可能会反复地执行完全相同的查询语句,每一次查询都会去查一次数据库,为了减少资源浪费,mybaits提供了一种缓存的方式(一级缓存)。
二级缓存:
二级缓存是全局的,也就是说;多个请求可以共用一个缓存,二级缓存需要手动开启。二级缓存针对的是同一个namespace,所以建议是在单表操作的Mapper中使用,或者是在相关表的Mapper文件中共享同一个缓存。一级缓存无过期时间,只有生命周期,缓存会先放在一级缓存中,当sqlSession会话提交或者关闭时才会将一级缓存刷新到二级缓存中;开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找,然后才去数据库查询;
6.分页查询插件
使用分页助手插件有三个步骤:
1> 导入pagehelper坐标
- <dependency>
- <groupId>com.github.pagehelper</groupId>
- <artifactId>pagehelper</artifactId>
- <version>5.3.2</version>
- </dependency>
2> 在核心配置文件中配置pageHelper
- <plugins>
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
- <!--设置方言-->
- <property name="helperDialect" value="mysql"/>
- </plugin>
- </plugins>
3> 测试
- //设置分页相关参数
- //pageNum 第几页 pageSize 一页多少条数据
- PageHelper.startPage(2,3);
- List<User> all = mapper.findAll();
- for (User u : all) {
- System.out.println(u);
- }
4> 一些相关的API
- // 获取与分页相关参数
- PageInfo<User> pageInfo = new PageInfo<User>(all);
- System.out.println("当前页:"+pageInfo.getPageNum());
- System.out.println("每页显示的条数:"+pageInfo.getPageSize());
- System.out.println("总条数:"+pageInfo.getTotal());
- System.out.println("总页数:"+pageInfo.getPages());
- System.out.println("上一页:"+pageInfo.getPrePage());
- System.out.println("下一页:"+pageInfo.getNextPage());
- System.out.println("是否是第一个:"+pageInfo.isIsFirstPage());
- System.out.println("是否是最后一个:"+pageInfo.isIsLastPage());
- System.out.println("所有参数信息:"+pageInfo.toString());
7.延时加载
MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。
延迟加载类型及设定:通过对全局参数:lazyLoadingEnabled进行设置,默认就是false。 进行设置修改延时加载状态。
直接加载: 执行完对主加载对象的select语句,马上执行对关联对象的select查询。
- <settings>
-
- <setting name="lazyLoadingEnabled" value="false"/>
- settings>
侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但要访问主加载对象的
某个属性(该属性不是关联对象的属性)时,就会马上执行关联对象的select查询。
- <settings>
-
- <setting name="lazyLoadingEnabled" value="true"/>
-
- <setting name="aggressiveLazyLoading" value="true"/>
- settings>
深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。
- <settings>
-
- <setting name="lazyLoadingEnabled" value="true"/>
-
- <setting name="aggressiveLazyLoading" value="false"/>
- settings>