它是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题。
使用框架的好处:
框架封装了很多的细节,使开发者可以使用极简的方式实现功能。大大提高开发效率。
表现层:
是用于展示数据的
业务层:
是处理业务需求
持久层:
是和数据库交互的
JDBC技术:
Connection
PreparedStatement
ResultSet
Spring的JdbcTemplate:
Spring中对jdbc的简单封装
Apache的DBUtils:
它和Spring的JdbcTemplate很像,也是对Jdbc的简单封装
以上这些都不是框架
JDBC是规范
Spring的JdbcTemplate和Apache的DBUtils都只是工具类
mybatis是一个持久层框架,用java编写的。
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
它使用了ORM思想实现了结果集的封装。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.qkongtao</groupId>
<artifactId>MyBatis1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
package dao;
import domain.User;
import java.util.List;
/**
*
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
<mappers>
<mapper resource="dao/IUserDao.xml"/>
</mappers>
<!--起别名,可以不用谢写全限定类名-->
<typeAliases>
<typeAlias type="domain.User" alias="user"></typeAlias>
</typeAliases>
</configuration>
<?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 namespace="dao.IUserDao">
<!--配置查询所有-->
<select id="findAll" resultType="domain.User">
select * from user
</select>
</mapper>
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
session.close();
in.close();
注意事项: 不要忘记在映射配置中告知mybatis要封装到哪个实体类中 配置的方式:指定实体类的全限定类名
把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句,同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。
package dao;
import domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
*
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
@Select("select * from user")
List<User> findAll();
}
明确: 我们在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式。不管使用XML还是注解配置。但是Mybatis它是支持写dao实现类的。
我们在实际开发中都会使用连接池。 因为它可以减少我们获取连接所消耗的时间。
mybatis中的连接池 mybatis连接池提供了3种方式的配置: 配置的位置: 主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
type属性的取值: 1. POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现 2. UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。 3. JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。 注意:如果不是web或者maven的war工程,是不能使用的。我们使用的是tomcat服务器,采用连接池就是dbcp连接池。
<select id="findUserByCondition" resultMap="userMap" resultType="domain.User">
select * from user where 1 =1
<if test="name != null">
and name = #{name}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</select>
<select id="findUserByCondition" resultMap="userMap" resultType="domain.User">
select * from user
<where>
<if test="name != null">
and name = #{name}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</where>
</select>
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。 * 在 QueryVo 中加入一个 List 集合用于封装参数
/**
package domain;/*
*Created by tao on 2020-03-26.
*/
import java.util.List;
public class QueryVo {
private User user;
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
/**
根据QueryVo中的提供的Id集合查询用户信息
*
* @param vo
* @return
*/
List<User> findUserInIds(QueryVo vo);
<!--根据QueryVo中的Id集合查询用户列表-->
<select id="findUserInIds" resultMap="userMap" parameterType="domain.QueryVo">
select * from user
<where>
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
foreach SQL语句 * 标签用于遍历集合,它的属性: * collection:代表要遍历的集合元素,注意编写时不要写#{} * open:代表语句的开始部分 * close:代表结束部分 * item:代表遍历集合的每个元素,生成的变量名 * sperator:代表分隔符
IUserDao配置如下
<?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 namespace="dao.IUserDao">
<!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
<!--一对一:定义 AccountUser 表的 accountMap-->
<resultMap id="accountMap" type="domain.AccountUser">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!-- 它是用于指定从表方的引用实体属性的 -->
<association property="user" javaType="domain.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="age" property="age"/>
</association>
</resultMap>
<!--一对多:定义 user 表的 userMap-->
<resultMap id="userMap" type="domain.User">
<!-- 主键字段的对应 -->
<id property="id" column="id"></id>
<!--非主键字段的对应-->
<result property="name" column="name"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="age" column="age"></result>
<!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型-->
<collection property="accounts" ofType="domain.Account">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
</collection>
</resultMap>
<!--多对多:定义 role 表的 ResultMap-->
<resultMap id="roleMap" type="domain.Role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="domain.User">
<id column="id" property="id"></id>
<result column="username" property="name"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!-- 一对一查询所有 -->
<select id="findAll" resultMap="accountMap">
select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
</select>
<!--一对多查询所有-->
<select id="findAllDuo" resultMap="userMap">
select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
a on u.id =a.uid
</select>
<!--一对多查询-->
<select id="findAllDDD" resultMap="roleMap">
select u.*,r.id as rid,r.role_name,r.role_desc from role r left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid;
</select>
</mapper>
我们需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。
<!-- 开启延迟加载的支持 -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
要用注解都用注解,要用xml都用xml,不能同时存在,不然会报错
像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提 高性能。 Mybatis 中缓存分为一级缓存,二级缓存。 1. 什么是缓存 存在于内存中的临时数据。 2. 为什么使用缓存 减少和数据库的交互次数,提高执行效率。 什么样的数据能使用缓存,什么样的数据不能使用 3. 适用于缓存: * 经常查询并且不经常改变的。 * 数据的正确与否对最终结果影响不大的。 4. 不适用于缓存: * 经常改变的数据 * 数据的正确与否对最终结果影响很大的。 * 例如:商品的库存,银行的汇率,股市的牌价。
在不修改数据库的情况下,查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis 提供给我们的一级缓存在起作用了。 **一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。 ** * 手动清空一级缓存 sqlSession.clearCache();//此方法也可以清空缓存
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。 二级缓存的使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
<!--配置二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
<!--开启二级缓存-->
<cache/>
第三步:让当前的操作支持二级缓存(在select标签中配置)
<!-- 一对一查询所有 -->
<select id="findAll" resultMap="accountMap" useCache="true">
select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
</select>