#MyBatis
####1:概念:
1:框架:是某种应用的半成品.是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题。
使用框架的好处:框架封装了很多细节,使开发者可以使用极简的方式实现功能,提高开发效率。
2:三层架构:
1:表现层:用于展示数据的
2:业务层:处理业务需求
3:持久层:是和数据库交互的
3:三层架构和SSM框架的对应关系:
1:表现层 ------> SpringMVC框架
2:Spring:Ioc(控制反转)和AOP(面向切面编程)
3:DAO:数据访问层 ------> MyBatis:持久层框架
*Service是业务层,Dao是数据访问层。Dao的作用是封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求;而Service,则是专注业务逻辑,对于其中需要的数据库操作,都通过Dao去实现。
4:持久层技术解决方案:
*JDBC技术:JDBC是规范,Java数据库连接
1: Connection
2: PrepareStatement
3: ResultSet
*Spring的JdbcTemplate:
Spring中对jdbc的简单封装
*Apache的DBUtils:
它和Spring的JdbcTemplate很像,也是对Jdbc的简单封装
*以上这些都不是框架。JDBC是规范,Spring的JdbcTemplate和Apache的DBUtils都只是工具类
####2:JDBC、Hibernate、mybatis的区别:
1:JDBC:JDBC-->Dbutils(QueryRunner)-->JdbcTemplate:工具
JDBC操作数据库: 编写sql-->预编译-->设置参数-->执行sql-->封装结果
不使用工具操作数据库的原因:
功能简单;sql语句编写在Java代码里面:硬编码高耦合的方式
JDBC操作数据库的弊端:
–SQL夹在Java代码块里,耦合度高导致硬编码内伤
–维护不易且实际开发需求中sql是有变化,频繁修改的情况多见
2:Hibernate
Hibernate框架:
全自动全映射ORM(Object Relation Mapping)框架;全自动(如全自动洗衣机)
旨在消除sql
把JavaBean对象映射成数据库里的记录:
JavaBean(Java对象) ----------------------------------------> DbRecords
(编写sql-->预编译-->设置参数-->执行sql-->封装结果)把这个过程交给Hibernate框架处理。
弊端:sql语句由框架写;失去灵活性
Hibernate和JPA操作数据库的弊端:
–长难复杂SQL,对于Hibernate而言处理也不容易
–内部自动生产的SQL,不容易做特殊优化。
–基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。导致数据库性能下降。
mybatis与hibernate的区别:
1.mybatis是把sql语句与java代码分离了,sql语句在xml文件配置里面。
2.hibernate封装地比较彻底,简化了dao层的编码工作,但是不够灵活。
3.hibernate数据库移植性远大于mybatis。
4.hibernate拥有完整的日志系统,mybatis则欠缺一些。
5.sql直接优化上,mybatis要比hibernate方便很多。
希望sql语句交给开发人员编写,希望sql不失去灵活性,所以有了Mybatis。
####3:MyBatis框架的概述:
半自动(如半自动洗衣机)、轻量级
把JavaBean对象映射成数据库里的记录:
JavaBean(Java对象) ----------------------------------------> DbRecords
(编写sql-->预编译-->设置参数-->执行sql-->封装结果)把编写sql拿出来在配置文件里写,其他步骤框架处理。
重点:把编写sql拿出来写在配置文件中!实现sql与Java编码分离:开发人员控制sql
解决数据的持久化问题的框架,提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
*基于Java的持久层框架,内部封装了JDBC,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
*通过xml或注解的方式将要执行的各种statement配置起来,并通过Java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为Java对象并返回。
是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。
MyBatis 避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集。
MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录
*采用ORM思想:
*Object Relational Mappging 对象关系映射
*就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表。
*实体类中的属性和数据库表的字段名称保持一致
*解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道就可以完成对数据库的持久化操作。
####4:Mybatis的优缺点
优点:
1、简单易学:
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活:
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合:
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射 。
5、提供对象关系映射标签,支持对象关系组建维护。
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳。
下载地址:https://github.com/mybatis/mybatis-3/
####5:特点
1:接口式编程
原生的方式: Dao ===> DaoImpl
mybatis: Mapper ===> xxMapper.xml
2:SqlSession代表和数据库的一次会话;用完必须关闭
3:SqlSession和connection一样都是非线程安全的,每次使用都应该去获取新的对象
4:mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
(将接口和xml进行绑定)
EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class);
5:两个重要的配置文件:
mybatis的全局配置文件:包括数据库连接池信息、事务管理器信息...系统运行环境信息
sql映射文件:保存了每一个sql语句的映射信息:
将sql抽取出来
Mybatis的功能架构分为:
1:API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
接口调用方式:基于Statement ID 、基于Mapper接口
数据增加接口、数据删除接口、数据查询接口、数据修改接口、配置信息维护接口
2:数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作
参数映射----------->SQL解析------>SQL执行------->结果处理和映射
(ParameterHandler) (SqlSource) (Executor) (ResultSetHandler)
参数映射配置 SQL语句配置 SimpleExecutor 结果映射配置
参数映射解析 SQL语句解析 BatchExecutor 结果类型转换
参数类型解析 SQL语句动态生成 ReuseExecutor 结果类型转换
3:基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
SQL语句配置方式:基于XML配置、 基于注解
事务管理、连接池管理、缓存机制
附:引导层:
基于XML配置方式、基于Java API方式
####6:MyBatis工作流程:
(1)加载配置并初始化
触发条件:加载配置文件
配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
(2)接收调用请求
触发条件:调用Mybatis提供的API
传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。
(3)处理操作请求 触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象
处理过程:
(A)根据SQL的ID查找对应的MappedStatement对象。
(B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
(C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(E)释放连接资源。
(4)返回处理结果将最终的处理结果返回。
####7:mybatis的入门:
1:环境搭建:
1:创建maven工程并导入坐标
2:创建实体类和dao的接口
3:创建Mybatis的主配置文件: SqlMapConfig.xml(基于学习案例)
4:创建映射配置文件:UserDao.xml(基于学习案例)
*注意事项:
1:创建UserDao.xml和UserDao.Java时名称是为了和我们之前的知识保持一致,
在mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper
所以:UserDao和UserMapper是一样的。
2:在idea中创建目录时,它和包是不一样的
包在创建时:是三级结构
目录在创建时:是一级目录
3:mybatis的映射配置文件位置必须和dao接口的包结构相同
4:映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
5:映射配置文件的操作配置,id属性的取值必须是dao接口的方法名。
当我们遵从了第3、4、5点之后,我们在开发中就无须再写dao的实现类。
2:入门案例:
1:读取配置文件
2:创建SqlSessionFactory工厂
3:使用工厂生产SqlSession对象
4:使用SqlSession创建Dao接口的代理对象
5:使用代理对象执行方法
6:释放资源
如:
public class MybatisTest {
public static void main(String[] args){
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findALL();
for(User user : users ){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
*注意事项:
不要忘记在映射配置中告知mybatis要封装到哪个实体类中
配置的方式:指定实体类的全限定类名
*mybatis基于注解的入门案例:
把UserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句,
同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。
*明确:
我们在开发中,都是越简便越好,所以都是采用不写dao实现类的方式,不管使用xml还是注解配置
。
但是mybatis它是支持写dao实现类的
3:自定义mybatis的分析:
将会涉及到的一些知识点:工厂模式(Factory工厂模式)、构造者模式(Builder模式)、代理模式,反射,自定义注解,注解的反射,xml解析,数据库元数据,元数据的反射等
*mybatis在使用代理dao的方式实现增删改查时做什么事?
两件事:
1:创建代理对象
2:在代理对象中调用selectList
*自定义mybatis能通过入门案例看到类:
**class Resources**
**class SqlSessionFactoryBuilde**r
**interface SqlSessionFactory**
**interface SqlSession**
1:查询所有的分析:
selectList方法:
1:根据配置文件的信息创建Connection对象
注册驱动,获取连接
2:获取预处理对象PreparedSatement
此时需要SQL语句
conn.prepareStatement(sql);
3:执行查询
ResultSet resultSet = preparedStatement.executeQuery();
4:遍历结果集用于封装
List<E> list = new ArrayList();
while(resultSet.next()){
E element = (E) Class.forName(配置的全限定类名).newInstance()
进行封装,把每个rs的内容都添加到element中
我们的实体类属性和表中的列名是一致的
于是我们就可以把表的列名看成是实体类的属性名称
就可以使用反射的方式来根据名称获取每个属性,并把值赋进去
把element加入到list中
list.add(element);
}
5:返回list
return list;
2:创建代理对象的分析:
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//根据dao接口的字节码创建dao的代理对象
public <T> T getMapper(Class<T> daoInterfaceClass){
/*
类加载器:它使用的和被代理对象是相同的类加载器
代理对象要实现的接口:和被代理对象实现相同的接口
如何代理:它就是增强的方法,我们需要自己来提供。
此处是一个InvocationHandler的接口,我们需要写一个该接口的实现类
在实现类中调用selecList方法
*/
Proxy.newProxyInstance(类加载器,代理对象要实现的接口字节码数组,如何代理);
}
4:自定义mybatisd的编码:
1:根据测试类中缺少的创建接口和类
####8:Mybatis框架原理:
全局配置文件(SqlMapConfig.xml)
(配置数据源、事务、加载映射文件)
|
|
映射文件文件
(配置statement的相关信息,如sql)
|
|
SqlSessionFactory
(SqlSessionFacotryBuild通过配置文件创建)
|
|
SqlSession
(该接口封装了一些对数据进行操作方法)
|
|
executor
SqlSession本身不直接操作数据库,而是通过该接口来操作数据库
|
|
MappedStatement
作用是封装了statement的相关信息,包括sql语句,输入参数和输出结果等
|
|
数据库
####9:Mybatis的环境搭建(代码步骤)
//目录结构:src /main/java/com/itheima/domian/User.java
/dao/IUserDao.Java
/resources/log4j.properties和SqlMapConfig.xml
/com/ithiema/dao/IUserDao.xml
/test/java/com/ithiema/test/MybatisTest.java
1:首先需要打开sql创建表
/*
user表:
id username birthday sex address
41 老张 2018-02-27 北京
42 小马 2018-02-27 青岛
44 老李 2018-02-27 天津
45 老吴 2018-02-27 上海
*/
2:创建Maven工程
如: GroupId:com.ithima
ArtifactId:day02_eesy_01mybatisCRUD
1://在pom.xml中
<packaging>jar</packaging>
//导入依赖坐标
<dependencies>
<dependency>
<groupId>org.mybatis</groudId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groudId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groudId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groudId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
2:把log4j.properties复制到resources中
3:在src/main/java包下写一个实体类User.java放在com.itheima.domain包下
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//生成getter/setter/toString方法
...
}
4:在resources下创建mybatis的主配置文件
//new File :SqlMapConfig.xml
//拷贝mybatis配置文件的约束中的Config的约束到里面
<?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">
//然后配置环境
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</dataSource>
</environment>
</environments>
<!--配置映射文件的位置-->
<mappers>
<mapper resource="com/itheima/dao/IuserDao.xml"></mapper>
</mappers>
</configuration>
5:在ithiema包下创建IUserDao.java接口, dao.IUserDao
//用户的持久层接口
public interface IUserDao{
//查询所有用户
List<User> findAll();
}
6:对应包的结构创建映射配置文件
//必须一级一级创建 new directory:在resources下创建com/ithiema/dao
//在dao下创建一个配置文件new File:IUserDao.xml
//把mybatis配置文件的约束中的Mapper的约束导入
<?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.ithiema.dao.IUserDao"> //namespace:是确定该方法是在哪个Dao接口
<!--查询所有-->
<select id="findAll" resultType="com.ithiema.domain.User"> //id:是指哪个方法;resultType:表示要封装到哪里去
select * from user; //sql语句
</select>
</mapper>
//以上即把mybatis环境搭建好了
//测试:
//在test/Java包下创建一个测试类: MybatisTest.java com.ithiema.test
//测试mybatis的crud操作
public class MybatisTest {
//测试查询所有
@Test
public void testFindAll() throws Exception {
//1:读取配置文件,生成字节输入流
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2:获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3:获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//4:获取dao的代理对象
IUserDao uesrDao = sqlSession.getMapper(IUserDao.class);
//5:执行查询所有方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6:释放资源
sqlSession.close();
in.close();
}
}
####9:Mybatis的CRUD
查询、保存、更新、删除操作
步骤:
//1:在IUserDao.java(用户的持久层接口)中写方法
public interface IUserDao {
/*查询所有用户
@param
@return
*/
List<User> findAll();
/*保存用户
@param user
@return
*/
void saveUser(User user);
//更新用户
void undateUser(User user);
//根据Id删除用户
void deleteUser(Integer usrId);
//根据Id查询用户信息
User findById(integer userId);
//根据名称模糊查询用户信息
List<User> findByName(String username);
//查询总用户数
int findTotal();
}
//2:在映射配置里面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.ithiema.dao.IUserDao"> //namespace:是确定该方法是在哪个Dao接口
<!--查询所有-->
<select id="findAll" resultType="com.ithiema.domain.User"> //id:是指哪个方法;resultType:表示要封装到哪里去
select * from user; //sql语句
</select>
<!--保存用户-->
<insert id="saveUser" parameterType="com.ithiema.domain.User"> //id:方法名称 ; parameterType:参数的类型
<!--配置插入操作后,获取插入数据的id-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,address,sex,birthday)value(#{
username},#{
address},#{
sex},#{
birthday});
</insert>
<!--更新用户-->
<update id="updateUser" parameterType="com.ithiema.domain.User">
update user set username=#{
username},address=#{
address},sex=#{
sex},birthday=#{
birthday} where id=#{
id}
</update>
<!--删除用户-->
<delete id="deleteUser" parameterType="Integer">
delete from user where id = #{
uid} //uid:随便写的占位符
</delete>
<!--根据id查询用户-->
<select id="findById" parameterType="INT" resultType="com.itheima.domain.User">
select * from user where id = #{
uid}
</select>
<!--根据名称模糊查询-->
<select id="fandByName" parameterType="string" resultType="com.itheima.domain.User">
select * from user where username like #{
name}
</select>
<!--获取用户的总记录条数-->
<select id="findTotal" resultType="int">
select count(id) from user;
</select>
</mapper>
//3:打开测试类:MybatisTest.java
public class MybatisTest {
//执行一些初始化的操作
private InputStream in ;
private SqlSession sqlSession;
private IUserDao userDao;
@Before //用于在测试方法执行之前执行
public void init() throws Exception{
//1:读取配置文件,生成字节输入流
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2:获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3:获取SqlSession对象
sqlSession = factory.openSession();
//4:获取dao的代理对象
uesrDao = sqlSession.getMapper(IUserDao.class);
}
@After //用于在测试方法执行之后执行
public void destroy() throws Exception{
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
in.close();
}
//测试查询所有
@Test
public void testFindAll() {
//5:执行查询所有方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
}
//测试保存操作
@Test
public void testSave(){
User user = new User();
user.setUsername("程序猿");
user.setAddress("重庆市");
user.setSex("男");
user.setBirthday(new Date());
//5:执行保存方法
userDao.saveUser(user);
}
//测试更新操作
@Test
public void tetUpdate(){
User user = new User();
user.setId(50);
user.setUsername("程序猴");
user.setAddress("成都市");
user.setSex("男");
user.setBirthday(new Date());
//执行更新方法
userDao.updateUser(user);
}
//测试删除操作
@Test
public void testDelete(){
//5.执行删除方法
userDao.deleteUser(45);
}
//测试删除操作
@Test
public void testFindOne(){
//5.执行查询一个方法
User user = userDao.findById(45);
System.out.println(user);
}
//测试模糊查询操作
@Test
public void testFindByName(){
//5.执行查询一个方法
List<User> users = userDao.findByName("%老%");
for(User user : users){
System.out.println(user);
}
}
//测试查询总记录条数
@Test
public void testFindTotal(){
//5.
int count = userDao.findTotal(;
System.out.println(count);
}
}
附:#{}表示一个占位符号通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
####10:Mybatis的深入
1:Mybatis中参数的深入
--使用实体类的包装对象作为查询条件
parameterType(输入类型):
传递简单类型
传递pojo对象
pojo对象:是JavaBean,即实体类对象
mybatis使用ognl表达式解析对象字段的值,#{}或${}括号中的值为pojo属性名称
传递pojo包装对象
ognl表达式:Obeject Graphic Navigation Language(对象图导航语言)
它是通过对象的取值方法来获取数据。在写法上把get给省略了
如:我们获取用户的名称:
类中的写法:user.getUsername();
OGNL表达式写法:user.username
mybatis中为什么能直接写username,而不用user.呢?
因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名
2:Mybatis中返回值的深入
--调整实体类属性解决增和改方法的报错
--解决实体类属性和数据库列名不对应的两种
问题:在实体类IUser.java中更改成员变量,导致实体类属性和数据库列名不对应
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
解决:
1第一种:最简单方式:起别名;
在IUserDao.xml中更改:
<!--查询所有-->
<select id="findAll" resultType="com.ithiema.domain.User">
select id as userId,username as UserName,address as userAdress,sex as usrSex,birthday as userBirthday from user; //sql语句
</select>
2第二种:采用配置的方法解决(这种方式可提高开发效率)
在IUserDao.xml中配置:
<!--配置 查询结果的列名和实体类的属性名的对应关系-->
<resultMap id="userMap" type="com.ithiema.domain.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>
在IUserDao.xml中更改:
<!--查询所有-->
<select id="findAll" resultMap="userMap">
select * from user; //sql语句
</select>
####11:Mybatis实现DAO层开发
通常有两个方法,即
1:原始dao开发方式
2:Mapper接口代理开发方式。
现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便。
####12:SqlMapConfig.xml配置文件
1:properties标签
可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置文件信息
resource属性:常用的
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
url属性:
是要求按照Url的写法来写地址
URL:Uniform Resource Locator :统一资源定位符,它是可以唯一标识的一个资源的位置
写法:
http://localhost:8080/mybatisserver/demo01Servlet
协议 主机 端口 URI
URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的
2:typeAlias标签
使用typeAlias配置别名,它只能配置domain中类的别名
type属性指定的是实体类全限定类名
alias属性指定别名
指定了别名,就不再区分大小写
如:
3:package标签:用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写
如:
在typeAlias标签下使用:
如:2:
在mapper标签下:
package标签是用于指定dao接口所在的包,当指定了之后就不需要再写mapper以及resource或者class了
####13:mybatis中的连接池以及事务控制
1:连接池
就是用于存储连接的容器,容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一连接,该集合还必须实现队列的特性:先进先出
我们在实际开发中都会使用连接池,因为它可以减少我们获取连接所消耗的时间
mybatis中的连接池:
myabtis连接池提供了3种方式的配置:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式
type属性的取值:
1:POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
2:UNPOOLED:采用传统的获取连接的方式,虽然也实现javax.sql.DataSource接口,但是并没有使用池的思想
3: JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的。
注意:如果不是web或者maven的war工程,是不能使用的。
我们课程中使用的是tomcat服务器。采用连接池就是dbcp连接池。
2:事务控制
(什么是事务、事务的四大特性、不考虑隔离性会产生的3个问题、解决方法:四种隔离级别):在MySQL中,复习
它是提供sqlsession对象的commit方法和roolback方法实现事务的提交和回滚
####14:mybatis基于xml配置的动态SQL语句使用
Dynamic SQL:动态SQL
动态SQL的标签:
<if>标签:
<if test="username != null">
username = #{
userName}
</if>
<where>标签:
<foreach>标签:用于遍历集合
它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{
}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
<sql>标签:....
####15:mybatis中的多表操作
表之间的关系:
一对多
多对一
一对一
多对多
mybatis中把多对一看成了一对一
步骤:
1:建立两张表:用户表、账户表
让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
2:建立两个实体类:用户实体类和账户实体类
让用户和账户的实体类能体现出一对多的关系
3:建立两个配置文件
用户的配置文件
账户的配置文件
4:实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息
当我们查询账户时,可以同时得到账户的所属用户信息
1:完成account一对一操作:建立实体类关系的方式
2:完成user的一对多查询操作:
一对多关系映射:主表实体应该包含从表实体的集合引用
3:多对多:
多对多的关系映射:一个用户可以具备多个角色
步骤:
1:建立两张表:用户表、账户表
让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
2:建立两个实体类:用户实体类和账户实体类
让用户和角色的实体类能体现出来多对多的关系
3:建立两个配置文件
用户的配置文件
账户的配置文件
4:实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息
当我们查询账户时,可以同时得到账户的所属用户信息
####16:mybatis中的延迟加载
延迟加载:在真正使用数据时才发起查询,不用时不查询。按需加载(懒加载)
lazyloadingEnabkled:延迟加载的全局开关。默认值false
立即加载:不管用不用,只要一调用方法,马上发起查询
在对应的四种表关系中:
一对多,多对多:通常情况下我们都是采用延迟加载
多对一,一对一:通常情况下我们都是采用立即加载
####17:mybatis中的缓存
缓存:存在于内存中的临时数据
为什么使用缓存:减少和数据库的交互次数,提高执行效率
什么数据能用缓存/不能用缓存:
适用于缓存的:经常查询并且不经常改变的、数据的正确与否对最终结果影响不大的。
不适用缓存的:经常改变的数据、数据的正确与否对最终结果影响很大的
mybatis中的一级缓存和二级缓存:
一级缓存:
它指的是Mybatis中SqlSession对象的缓存。
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否由,有的话直接拿出来用。
当SqlSession对象消失时,mybatis的一级缓存也就消失了。
清空一级缓存:级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除、commit()、close()等方法时,就会清空一级缓存
二级缓存:
它指的是mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存使用步骤:
1:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
2:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
3:让当前的操作支持二级缓存(在select标签中配置)
####18:mybatis中的注解开发
环境搭建
单表CRUD操作(代理DAO方式)
多表查询操作
缓存的配置