一. 三层架构
界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。
三层对应的包
界面层: controller包 (servlet)
业务逻辑层: service 包(XXXService类)
数据访问层: dao包(XXXDao类)
三层中类的交互
用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)
三层对应的处理框架
界面层—servlet—springmvc(框架)
业务逻辑层—service类–spring(框架)
数据访问层—dao类–mybatis(框架)
二.框架
模版:
- 规定了好一些条款,内容。
- 加入自己的东西
框架特点:
- 框架一般不是全能的, 不能做所有事情
- 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
- 框架是一个软件
三.mybatis框架
介绍: 一个框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
(1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据
(2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。
mybatis提供了哪些功能:
提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
提供了执行sql语句的能力, 不用你执行sql
提供了循环sql, 把sql的结果转为java对象, List集合的能力
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt(“id”));
stu.setName(rs.getString(“name”));
stu.setAge(rs.getInt(“age”));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
}
4.提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。
3.1 开发mybatis程序从步骤:
1.配置mybatis
(1)conf.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">
<configuration>
<!--通过environments的default值和environment的id来制定MyBatis运行时的数据库环境-->
<environments default="development">
<!--开发环境(自己的计算机)-->
<environment id="development">
<!--事务提交方式:
JDBC:利用JDBC方式处理事务(commit rollback close)
MANAGED:将事务提交由其他组件去托管(spring,jobss),默认会关闭连接。
-->
<transactionManager type="JDBC"/>
<!--数据源类型:
UNPOOLED:传统JDBC模式(每次访问数据库,均需要打开,关闭等数据库)
POOLED:使用数据库连接池
JNDI:从tomcat中获取一个内置的数据库连接池(数据库连接池-数据)
-->
<dataSource type="POOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:ORCL"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载映射文件 -->
<mapper resource="org/lanqiao/entity/personMapper.xml"/>
</mappers>
</configuration>
注意事项:
如果使用的 事务方式为 jdbc,则需要 手工commit提交,即session.commit();
(2)映射文件personMapper.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="org.lanqiao.entity.personMapper">
<!--mybatis约定:输入参数parameterType 和 输出参数resultType ,在形式上都只能有一个-->
<select id="queryPersonById" resultType="org.lanqiao.entity.Person" parameterType="int">
select * from person where id = #{id}
</select>
</mapper>
输出参数: 如果返回值类型是一个 对象(如Student),则无论返回一个、还是多个,
resultType都写成org.lanqiao.entity.Student
(3)测试类:
session.selectOne(“需要查询的SQL的namespace.id”,“SQL的参数值”);
public class TestMyBatis {
public static void main(String[] args) throws IOException {
//加载MyBatis配置文件(为了访问数据库)
Reader reader = Resources.getResourceAsReader("conf.xml") ;
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader) ;
//session - connection
SqlSession session = sessionFactory.openSession() ;
String statement = "org.lanqiao.entity.personMapper.queryPersonById" ;
Student person = session.selectOne( statement,1 ) ;
System.out.println(person);
session.close();
}
3.2 mapper动态代理方式的CRUD(MyBatis接口开发):
原则:约定优于配置
硬编码方式
abc.java
Configuration conf = new Configuration();
con.setName(“myProject”) ;
配置方式:
abc.xml
myProject
约定:默认值就是myProject
1.具体实现的步骤:
1.基础环境:mybatis.jar/ojdbc.jar、conf.xml、mapper.xml
2.(不同之处)
约定的目标: 省略掉statement,即根据约定 直接可以定位出SQL语句
a.接口,接口中的方法必须遵循以下约定:
方法名和mapper.xml文件中标签的id值相同
方法的 输入参数 和mapper.xml文件中标签的 parameterType类型一致 (如果mapper.xml的标签中没有 parameterType,则说明方法没有输入参数)
方法的返回值 和mapper.xml文件中标签的 resultType类型一致 (无论查询结果是一个 还是多个(student、List),在mapper.xml标签中的resultType中只写 一个(Student);如果没有resultType,则说明方法的返回值为void)
(List ),在mapper.xml标签中的resultType中只写 一个(Student);如果没有resultType,则说明方法的返回值为void)
package org.lanqiao.mapper;
import java.util.List;
import org.lanqiao.entity.Student;
//操作Mybatis的接口 需要和StudenetMapper.xml配置文件一个目录
public interface StudentMapper {
// public abstract Student queryStudentByStuno(int stuno);
Student queryStudentByStuno(int stuno);
//查询全部
List<Student> queryAllStudents();
//增加
void addStudentWithConverter(Student student);
void addStudent(Student student);
//删除
void deleteStudentByStuno(int stuno);
//修改
void updateStudentByStuno(Student student);
Student queryStudentByStunoWithConverter(int stuno);
除了以上约定,要实现 接口中的方法 和 Mapper.xml中SQL标签一一对应,还需要以下1点:
namespace的值 ,就是 接口的全类名( 接口 - mapper.xml 一一对应)👴
匹配的过程:(约定的过程)
根据 接口名 找到 mapper.xml文件(根据的是namespace=接口全类名)
根据 接口的方法名 找到 mapper.xml文件中的SQL标签 (方法名=SQL标签Id值)
以上2点可以保证: 当我们调用接口中的方法时,程序能自动定位到 某一个Mapper.xml文件中的sqL标签
习惯:SQL映射文件(mapper.xml) 和 接口放在同一个包中 (注意修改conf.xml中加载mapper.xml文件的路径)
3.以上,可以通过接口的方法->SQL语句
执行:
StudentMapper studentMapper = session.getMapper(StudentMapper.class) ;
studentMapper.方法();
//可以通过build的第二参数 指定数据库环境
SqlSessionFactory sessionFacotry = new SqlSessionFactoryBuilder().build(reader,"development") ;
SqlSession session = sessionFacotry.openSession() ;
StudentMapper studentMapper = session.getMapper(StudentMapper.class) ;
Student student = studentMapper.queryStudentByStuno(2) ;//接口中的方法->SQL语句
System.out.println(student);
session.close();
通过session对象获取接口(session.getMapper(接口.class);),再调用该接口中的方法,程序会自动执行该方法对应的SQL。
四. 优化(属性文件,全局参数,别名,类型转换器,resultMap)
4.1 属性文件
可以将配置信息 单独放入 db.properties文件中,然后再动态引入
db.properties:
k=v
<configuration>
<properties resource="db.properties"/>
</configuration>
引入之后,使用${key}
4.2 MyBatis全局参数
在conf.xml中设置
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="lazyLoadingEnabled" value="false" />
</settings>
4.3 别名 conf.xml
<!-- 设置单个/多个别名 -->
<typeAliases>
<!-- 单个别名 (别名 忽略大小写) -->
<typeAlias type="org.lanqiao.entity.Student" alias="student"/>
<!-- 批量定义别名 (别名 忽略大小写),以下会自动将该包中的所有类 批量定义别名: 别名就是类名(不带包名,忽略大小写) -->
<package name="org.lanqiao.entity"/>
</typeAliases>
4.4 类型处理器(类型转换器)
1.MyBatis自带一些常见的类型处理器
int - number
2.自定义MyBatis类型处理器
java -数据库(jdbc类型)
示例:
实体类Student : boolean stuSex
true:男
false:女
表student: number stuSex
1:男
0:女
自定义类型转换器(boolean -number)步骤:
a.创建转换器:需要实现TypeHandler接口
通过阅读源码发现,此接口有一个实现类 BaseTypeHandler ,因此 要实现转换器有2种选择:
i.实现接口TypeHandler接口
ii.继承BaseTypeHandler
b.配置conf.xml
4.5 resultMap可以实现2个功能:
1.类型转换
2.属性-字段的映射关系
<select id="queryStudentByStuno" parameterType="int" resultMap="studentMapping" >
select * from student where stuno = #{stuno}
<!--insert into student(stuno,stuname,stuage,graname,stusex) values(#{stuNo},#{stuName},#{stuAge},#{graName} ,#{stuSex ,javaType=boolean ,jdbcType=INTEGER } )-->
</select>
<resultMap type="student" id="studentMapping">
<!-- 分为主键id 和非主键 result-->
<id property="id" column="stuno" />
<result property="stuName" column="stuname" />
<result property="stuAge" column="stuage" />
<result property="graName" column="graname" />
<result property="stuSex" column="stusex" javaType="boolean" jdbcType="INTEGER"/>
</resultMap>
4.6 两种取值符号,ParameterType输入参数类型
1.类型为简单类型(8个基本类型+String)
#{} ${}
2.对比
相同:都可以获取对象的值,对象类型的时候,都需要${}#{} 写属性名
<!--mybatis约定:输入参数parameterType 和 输出参数resultType ,在形式上都只能有一个-->
<select id="queryPersonById" resultType="org.lanqiao.entity.Person" parameterType="int">
select * from person where id = #{id} //${value}
</select>