目录
1.框架概述
1.1 三层架构
三层架构包括界面层、业务逻辑层、数据访问层。
①界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。(jsp、
html、servlet)
②业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取
数据。
③数据访问层(持久层):与数据库打交道。主要实现对数据的增、删、改、查,将存储在数据
库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。
三层对应的包:
①界面层:controller包(XXXServlet类)
②业务逻辑层:service包(XXXService类)
③数据访问层:dao包(XXXDao类)
三层中类的交互:
用户使用界面层--->业务逻辑层--->数据访问层--->数据库
三层对应的处理框架:
界面层---servlet类---springmvc框架
业务逻辑层---service类---spring框架
数据访问层---dao类---mybatis框架
1.2 框架
框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例件交互的方法,也可以将框架看成是可被应用开发者定制的应用骨架、模板。简单地说,框架其实是半成品软件,就是一组组件,供你使用来完成你自己的系统。框架是安全的、可复用的、不断升级的软件。
框架中定义好了一些基础功能,可以在项目中加入自己的功能,而自己加入的功能也可以利用框架中写好的功能。
框架特点:
①框架一般不是全能的,不能做所有事情;
②框架是针对某一领域有效,特长在某一方面,比如mybatis做数据库操作强,但不擅长做其
他的;
③框架是一个软件。
2.Mybatis框架概述
2.1 JDBC的缺陷
①代码比较多,开发效率低;
②需要关注Connection、Statement、ResultSet对象的创建和销毁;
③对ResultSet查询的结果,需要自己封装为List;
④重复的代码比较多;
⑤业务代码和数据库的操作混在一起。
2.2 Mybatis框架概述
mybatis框架,早期叫做ibatis,其源代码在github上。
mybatis是MyBatis SQL Mapper Framework for Java(sql映射框架),包括:
①sql maper:sql映射。可以吧数据库表中的一行数据映射为一个java对象,即一行数据可以
看作是一个java对象,操作这个对象,就相当于操作表中的数据。
②Data Access Objects(Daos):数据访问,对数据库执行增删改查。
mybatis提供的功能:
①提供了创建Connection、Statement、ResultSet的能力,不需要开发人员创建这些对象。
②提供了执行sql语句的能力,不用开发人员执行sql语句。
③提供了循环sql,把sql的结果转为java对象、List集合的能力。
在JDBC中只能:
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);
}
④提供了关闭资源的能力,不用自己手动关闭Connection、Statement、ResultSet。
流程:开发人员提供sql语句---mybatis处理执行sql语句---开发人员得到List集合或Java对象(表中的数据)
总结:mybatis是一个sql映射框架,提法对数据库的操作能力,相当于增强的JDBC。使用mybatis可以让开发人员集中精力写sql语句就可以了,不用关心Connection、Statement、ResultSet的创建、销毁以及sql语句的执行。
3.Mybatis的入门案例
1.创建mysql数据库和表。数据库名springdb;表名student。
2.新建一个maven项目,骨架选择maven-archetype-quickstart即可。在pom.xml文件中加入mybatis、mysql驱动的依赖。
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--sql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
3.创建实体类,Student类,用来保存表中的一行数据。实体类的包名叫domain或者entity。
package com.bjpowernode.domain;
//推荐和表名一样,容易记忆
public class Student {
//定义属性,目前要求是属性名和列名一样。
private Integer id;
private String name;
private String email;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
4.创建数据访问层的dao接口,定义操作数据库的方法。包名叫做dao。
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import java.util.List;
//接口操作Student表
public interface StudentDao {
//查询Student表的所有数据
public List<Student> selectStudents();
//插入方法
//参数:student,表示要插入到数据库的数据
//返回值:int 表示执行insert操作后的影响数据库的行数(成功添加了几行数据 )
public int insertStudent(Student student);
}
5.创建一个mybatis使用的配置文件,叫做sql映射文件,用来写sql语句的。一般一个表一个sql映射文件,这个文件是xml文件。该文件写在dao接口所在的目录中(dao文件夹),文件名称和dao接口名称保持一致。StudentDao.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.bjpowernode.dao.StudentDao">
<select id="selectStudents" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student order by id
</select>
<!--
select:表示查询操作。
id:你要执行的sql语法的唯一标识,mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名称。
resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
值写的类型的全限定名称
-->
<select id="insertStudent">
insert into student values (#{id},#{name},#{email},#{age})
</select>
</mapper>
<!--
sql映射文件(sql mapper):写sql语句的,mybatis会执行这些sql
1.指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的。
2.约束文件的作用:限制,检查在当前文件中出现的标签、属性必须符合mybatis的要求
3.mapper:是当前文件的根标签,必须的。
namespace:叫做命名空间,唯一值的,可以是自定义的字符串。
要求使用dao接口的全限定名称
4.在当前文件中可以使用特定的标签,表示数据库的特定操作。
<select>:表示执行查询,select语句
<update>:表示更新数据库的操作,就是在<update>标签中写的是update语句
<insert>:表示插入,放的是insert语句
<delete>:表示删除,执行的是delete语句
-->
6.创建mybatis的主配置文件:一个项目就一个主配置文件,主配置文件提供了数据库的连接信息和sql映射文件的位置信息。写在resources文件夹中。mybatis.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>
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--
环境配置:数据库的连接信息
default:必须和某个environment的id值一样。
告诉mybatis使用哪个数据库的连接信息,也就是访问哪个数据库。
-->
<environments default="mydev">
<!--
environment:一个数据库信息的配置,环境
id:一个唯一值,自定义,表示环境的名称。
-->
<environment id="mydev">
<!--
transactionManager:mybatis的事务类型
type:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源的类型,POOLED表示使用连接池
-->
<dataSource type="POOLED">
<!--
driver,url,username,password是固定的,不能自定义。
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
<!--表示线上的库,是项目真实使用的库-->
<environment id="online">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/onlinedb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--sql mapper(sql映射文件)的位置-->
<mappers>
<!--
一个mapper标签指定一个文件的位置。
从类路径开始的路径信息。 target/classes(类路径)
-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml"/>-->
</mappers>
</configuration>
<!--
mybatis的主配置文件:主要定义了数据库的配置信息,sql映射文件的位置
1.约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2.configuration 根标签
-->
7.创建使用mybatis类,通过mybatis访问数据库。
package com.bjpowernode;
import com.bjpowernode.domain.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis,读取student数据
//1.定义mybatis主配置文件的名称,从类路径的跟开始(target/classess)
String config = "mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6.[重要]指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
//7.执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqiId);
//8.输出结果
//studentList.forEach( stu -> System.out.println(stu));
for (Student stu:studentList){
System.out.println(stu);
}
//9.关闭SqlSession对象
sqlSession.close();
}
}
public class TestMybatis {
//测试方法,测试功能
@Test
public void testInsert() throws IOException {
//访问mybatis,读取student数据
//1.定义mybatis主配置文件的名称,从类路径的跟开始(target/classess)
String config = "mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
//SqlSession sqlSession = factory.openSession();
SqlSession sqlSession = factory.openSession(true);//自动提交事务
//6.[重要]指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "insertStudent";
//7.执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1005);
student.setName("关羽");
student.setEmail("guanyu@163.com");
student.setAge(20);
int num = sqlSession.insert(sqiId,student);
//mybatis默认不是自动提交事务的,所以在insert,update,delete后要手工提交事务
//sqlSession.commit();
//8.输出结果
System.out.println("执行insert结果:" + num);
//9.关闭SqlSession对象
sqlSession.close();
}
}
8.创建一个工具类来实现前半部分重复的代码。
package com.bjpowernode.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
try {
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if(factory != null){
sqlSession = factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
9.利用工具类来实现查询功能。
public class MyApp2 {
public static void main(String[] args) throws IOException {
//[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//[重要]指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
//执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqiId);
//输出结果
//studentList.forEach( stu -> System.out.println(stu));
for (Student stu:studentList){
System.out.println(stu);
}
//9.关闭SqlSession对象
sqlSession.close();
}
}
在该例子中并没有使用到dao接口,这个接口不是必须的,但是在我们之后的开发中都是利用这个接口中的方法来访问数据库,进行增删改查操作。
4.Mybatis中主要类的介绍
4.1 Resources类
Resources是mybatis中的一个类,负责读取主配置文件。
InputStream in = Resources.getResourceAsStream("mybatis.xml");
4.2 SqlSessionFactoryBuilder类
负责创建SqlSessionFactory对象。
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
4.3 SqlSessionFactory接口
重量级对象,程序创建一个该对象耗时比较长,使用资源比较多。在整个项目中,这个对象有一个就够了,因此可以利用工具类中的静态代码块来创建。
SqlSessionFactory:接口。接口实现类:DefaultSqlSessionFactory。
SqlSessionFactory作用: 获取SqlSession对象。
SqlSession sqlSession = factory.openSession();
关于openSession()方法说明:
1. openSession() :无参数的,获取是非自动提交事务的SqlSession对象
2. openSession(boolean):
openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
4.4 SqlSession接口
定义了操作数据的方法,例如selectOne() selectList() insert() update() delete() commit() rollback()。
SqlSession接口的实现类DefaultSqlSession。
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close()。这样能保证他的使用是线程安全的。
5.关于入门案例的修改
5.1 传统dao的使用方式
1.dao接口:
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import java.util.List;
public interface StudentDao {
List<Student> selectStudents();
int insertStudent(Student student);
}
2.dao接口的实现类:
package com.bjpowernode.dao.impl;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlid = "com.bjpowernode.dao.StudentDao.selectStudents";
//执行sql语句,使用SqlSession类的方法
List<Student> students = sqlSession.selectList(sqlid);
sqlSession.close();
return students;
}
@Override
public int insertStudent(Student student) {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlid = "com.bjpowernode.dao.StudentDao.insertStudent";
//执行sql语句,使用SqlSession类的方法
int nums = sqlSession.insert(sqlid,student);
//提交事务
sqlSession.commit();
sqlSession.close();
return nums;
}
}
3.测试方法:
public class TestMyBatis {
@Test
public void testSelectStudents(){
//com.bjpowernode.dao.StudentDao
StudentDao dao = new StudentDaoImpl();
/*
List<Student> students = dao.selectStudents(); 调用
1.dao对象,类型是StudentDao,全限定名称是: com.bjpowernode.dao.StudentDao
全限定名称和namespace是一样的。
2.方法名称,selectStudents,这个方法名称就是mapper文件中的id值
1和2获得的字符串拼接后就是之前我们需要使用的sqlid
3.通过dao中方法的返回值类型也可以确定MyBatis要调用的SqlSession的方法
如果返回值类型是List,调用的是SqlSession.selectList() select方法
如果返回值类型是int,或者是非List的,看mapper文件中的标签是<insert>,<update>就会调用
SqlSession的insert,update等方法
这样就发现通过一个方法调用可以获得以上信息,因此可以利用反射机制。
mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息。
mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象。
完成SqlSession调用方法,访问数据库。
所以不需要自己手写dao的实现类。mybatis会利用动态代理自动实现。
*/
List<Student> students = dao.selectStudents();
for(Student student : students){
System.out.println(student);
}
}
@Test
public void testInsertStudent(){
StudentDao dao = new StudentDaoImpl();
Student student = new Student();
student.setId(1006);
student.setName("盾山");
student.setEmail("dunshan@163.com");
student.setAge(22);
int nums = dao.insertStudent(student);
System.out.println("添加对象的数量:" + nums);
}
}
5.2 使用Mybatis的动态代理
1.dao接口:
public interface StudentDao {
List<Student> selectStudents();
int insertStudent(Student student);
}
2.利用动态代理的测试方法:
SqlSession的对象有一个方法getMapper()。
public class TestMyBatis {
@Test
public void testSelectStudents(){
/**
* 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
* getMapper能获取dao接口对应的实现类对象。
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);//利用反射机制
//dao=com.sun.proxy.$Proxy2:JDK的动态代理
System.out.println("dao=" + dao.getClass().getName());
//调用dao的方法,执行数据库的操作
List<Student> students = dao.selectStudents();
for (Student student : students){
System.out.println(student);
}
sqlSession.close();
}
@Test
public void testInsertStudent(){
Student student = new Student();
student.setId(1007);
student.setName("李飞");
student.setEmail("lifei@163.com");
student.setAge(22);
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
int nums = dao.insertStudent(student);
sqlSession.commit();
System.out.println("添加对象的数量:" + nums);
sqlSession.close();
}
}
PS:根据动力节点课程整理,如有侵权,联系删除。