Mybatis的概述
mybatis是一个持久层框架,用java编写的。
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
它使用了ORM思想实现了结果集的封装。
ORM:
Object Relational Mapping对象关系映射
简单的说,就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表。
mybatis的环境搭配
<!--打包方式-->
<packaging>jar</packaging>
<!--导入-->
<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.6</version>
</dependency>
<!--日志坐标-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
Mybatis的入门
mybatis的环境搭建
第一步:创建maven工程并导入坐标
第二步:创建实体类和dao的接口
第三步:创建Mybatis的主配置文件
SqlMapConifg.xml
第四步:创建映射配置文件
IUserDao.xml
环境搭建的注意事项:
第一个:创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。
在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper
所以:IUserDao 和 IUserMapper是一样的
第二个:在idea中创建目录的时候,它和包是不一样的
包在创建时:com.itheima.dao它是三级结构
目录在创建时:com.itheima.dao是一级目录
第三个:mybatis的映射配置文件位置必须和dao接口的包结构相同
第四个:映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
第五个:映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名当我们遵从了第三,四,五点之后,我们在开发中就无须再写dao的实现类。
使用xml的环境搭配
1.创建Maven工程,在pom.xml文件中配置环境坐标
<packaging>jar</packaging>
<!--导入-->
<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.6</version>
</dependency>
2。写一个类和数据库表中的字段一 一对应起来
3.写一个查询的接口类
public interface IUserDao {
List<User> findAll();
}
4.在resources文件中写一个SqlMapConfig.xml文件进行配置
<?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/dyt"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"/>
</mappers>
</configuration>
5.在resources中配置一个和java类中dao包同等的目录,IuserDao.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">
<mapper namespace="com.itheima.dao.IUserDao" >
<!--配置查询所有-->
<select id="findAll" resultType="com.itheima.domain.User">
SELECT * from USER ;
</select>
</mapper>
6.在测试类中编写码,进行测试
public class MybatisTest {
public static void main(String[] args) throws Exception {
//1 读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2 创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3 使用工厂生产session对象
SqlSession session = factory.openSession();
//4 使用SqlSession创建Dao接口的代理对象
IUserDao users = session.getMapper(IUserDao.class);
//5 使用代理对象执行方法
List<User> all = users.findAll();
for(User user:all){
System.out.println(user);
}
//6 释放资源
in.close();
session.close();
}
}
使用注解的环境搭配
过程重复上面的,不需要写步骤4 ,在SqlMapConfig.xml文件中,Map对象写成class
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 <mapper resource="com/itheima/dao/IUserDao.xml"/>
如果是用注解来配置的话,此应该使用class属性指定被注解的dao全限定类名
-->
<mappers>
<!--<mapper resource="com/itheima/dao/IUserDao.xml"/>-->
<mapper class="com.itheima.dao.IUserDao"/>
</mappers>
</configuration>
在Dao的接口中直接使用注解方式进行写sql语句
public interface IUserDao {
@Select("select * from user")
List<User> findAll();
}
Mybatis的CRUD
保存数据
1.在dao的接口中增加save的方法
2.在resources中IUSerDao.xml文件,写入sql语句 赋值的格式为 #{写入参数值}
3.在测试中进行测试
更新数据
1.在dao接口中写入更新的接口方法
2.在resources中的IUserDao.xml中写入更新的SQL语句
3.在测试进行测试
删除数据
1.在dao接口中写入删除的接口方法【参数只写int id】
2.在resources中的IUserDao.xml中写入更新的SQL语句 【参数只写int 】
3.在测试进行测试
根据id查询该用户信息
1.在dao接口中写入根据id查询的接口方法【参数只写int id】【返回值是User】
2.在resources中的IUserDao.xml中写入根据id查询的SQL语句 【参数只写int 】
3.在测试进行测试
模糊查询
1.在dao接口中写入根据String name查询的接口方法【参数只写String name】【返回值是User】
2.在resources中的IUserDao.xml中写入根据String name查询的SQL语句 【参数只写String 】【模糊查询用的是like】
3.在测试进行测试
selectKey作用是:查询出保存数据的id值
使用实体类的包装对象作为查询条件
创建QueryVo
public class QueryVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
在dao接口中增加查询方法
/* 实体类的包装对象作为查询条件 */ List<User> findByVo(QueryVo vo);
在resources中写入sql语句
<!--根据包装类作为查询对象--> <select id="findByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User"> SELECT * from USER where username like #{user.username}; </select>
当字段和数据库的不一致是,解决办法
<!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="userMap" type="uSeR"> <!-- 主键字段的对应 --> <id property="userId" column="id"></id> <!--非主键字段的对应--> <result property="userName" column="username"></result> <result property="userAddress" column="address"></result> <result property="userSex" column="sex"></result> <result property="userBirthday" column="birthday"></result> </resultMap>
resultMap 使用id的
typeAliases(类型别名)
在 SqlMapConfig.xml 中配置: <typeAliases> <!-- 单个别名定义 --> <typeAlias alias="user" type="com.itheima.domain.User"/> <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> <package name="com.itheima.domain"/> <package name="其它包"/> </typeAliases>
Mybatis连接池
mybatis提供了3种方式的配置
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。type属性的取值:
POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。
注意:如果不是web或者maven的war工程,是不能使用的。
我们课程中使用的是tomcat服务器,采用连接池就是dbcp连接池。
Mybatis的sql动态查询
if查询
<select id="findByCondition" resultType="User" parameterType="User" > SELECT * from USER where 1=1 <if test="username !=null"> AND username =#{username}; </if >
where查询
<select id="findByCondition" resultType="User" parameterType="User"> SELECT * from USER <where> <if test="username !=null"> AND username =#{username} </if> <if test="sex !=null" > AND sex =#{sex} </if> </where> </select>
forech查询
<select id="findByIds" parameterType="com.itheima.domain.QueryVo" resultType="User"> select * from USER <where> <if test="ids !=null and ids.size()>0"> <foreach collection="ids" open="and id in (" close=")" item="id" separator=","> #{id} </foreach> </if> </where> </select>
Mybatis的多表查询
一对一查询
在从表中封装一个主表 ,在resultMap中封装User和Account
一对多
在主表中定义从表的属性,配置xml信息
标签
1.properties 标签引入 ,jdbc的文件
<properties resource="jdbcConfig.properties"></properties>
2. <typeAliases>标签是,给路径起别名,方便开发使用
<typeAliases> <package name="com.itheima.domain"></package> </typeAliases>
3.package省去了resources 和class
<mappers> <package name="com.itheima.dao"></package> </mappers>
Mybatis的缓存
Mybatis的延迟加载
什么是延迟加载:
在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
什么是立即加载
不管用不用,只要一调用方法,马上发起查询。
在对应的四种表关系中:一对多,多对一,一对一,多对多
一对多,多对多:通常情况下我们都是采用延迟加载
多对一,一对一:通常情况下我们都是采用立即加载。
延迟加载配置
1 在SqlMapConfig.xml文件中,配置延迟加载
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"></setting> </settings>
2 select 标签导入条件
<association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById"></association>
思想:在用的时候,调用对方的配置文件,不需要自己写
缓存
什么是缓存:
存在于内存中的临时数据
为什么使用缓存
减少和数据的交互次数,提高执行效率
什么样的数据能使用缓存,什么样的数据不能使用
- 适用与缓存
- 经常查询并且不经常改变的
- 数据的正确与否对最终结果影响不大的
- 不适用于缓存
- 经常改变的数据
- 数据的正确与否对最终结果影响很大的
Mybatis的一级缓存
它指的是Mybatis中的SqlSession对象的缓存。
当我们执行查询之后,查询结果会同时存入到SqlSession为我们提供一块区域中。
该区域的结构是一个Map.当我们再次查询同样的数据,Mybatis会先去SqlSession中查询是否有,有的话直接拿出来用。
当SqlSession对象消失时,mybatis的一级缓存也就消失了
SqlSession消失有两种方法 一个是close关闭,另一个是clearCache
一级缓存是SqlSession范围的缓存,当调用SqlSession的修改,添加,删除,commit,close等方法时,就会清空一级缓存
Mybatis的二级缓存
它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建SqlSession共享其缓存。
二级缓存的使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlSessionConfig.xml中配置)
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置) <cache></cache>
第三步:让当前的操作支持二级缓存(在select标签中配置)
mybatis的注解开发
省去了在resources里的IUserDao.xml文件的配置,直接在接口总使用注解即可
当数据库中的字段和属性的字段名称不一致是,可以使用results的注解
别的方法也想用这个配置,可以使用ResultMap注解【要在第一个配置中加入id属性】
注意:
1.可以在工厂创建session对象的时,参数写true,可以不用写提交事务 【手动提交改成自动提交】
factory。openSession(true);
2.多次用到一个sql语句,可以将此sql语句抽取出来,select * from user;<sql id="default"> select * from user </sql>
引用
< select id = "findAll" resultType = "user" >< include refid = "defaultSql" ></ include ></ select >