1.0 概述
1.三层架构
界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。
三层对应的包
界面层: controller包 (servlet)
业务逻辑层: service 包(XXXService类)
数据访问层: dao包(XXXDao类)
三层中类的交互
用户使用界面层--> 业务逻辑层--->数据访问层(持久层)-->数据库(mysql)
三层对应的处理框架
界面层---servlet---springmvc(框架)
业务逻辑层---service类--spring(框架)
数据访问层---dao类--mybatis(框架)
2.框架
框架是一个舞台, 一个模版
模版:
1. 规定了好一些条款,内容。
2. 加入自己的东西
框架是一个模块
1.框架中定义好了一些功能。这些功能是可用的。
2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。
框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
框架特点:
1. 框架一般不是全能的, 不能做所有事情
2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
3. 框架是一个软件
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);
} - 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet
的创建,销毁,sql的执行。
1.1 使用 Mybatis 准备
下载 mybatis
https://github.com/mybatis/mybatis-3/releases
1.2 搭建 MyBatis 开发环境
(1) 创建 mysql 数据库和表
数据库名 ssm ;表名 student
CREATE TABLE `student` (
`id` int(11) NOT NULL ,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(2) 创建 maven 工程
添加模块:
创建 maven 工程,信息如下:
选择模板:
加入
archetypeCatalog
Internal
这两行代码
目的:加速Maven项目的加载
然后点击 完成->应用 即可
新建一个resources目录,鼠标右键该resources,选择标记目录为并设置为Test Resources根
(3) 删除默认创建的 App 类文件
(4) 在pom.xml文件中加入 maven 坐标
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
</dependencies>
(5) 在pom.xml文件中加入 maven 插件
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
(6) 编写 Student 实体类(setter,getter,toString)
创建包 com.zep.domain, 包中创建 Student 类
项目结构如下所示:
Student.java文件:
package com.zep.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 +
'}';
}
}
(7) 编写 Dao 接口 StudentDao
创建 com.zep.dao 包,创建 StudentDao 接口
StudentDao.java文件:
package com.zep.dao;
import com.zep.domain.Student;
import java.util.List;
// 接口,操作student表
public interface StudentDao {
//查询student表中的所有数据
List<Student> selectStudents();
//插入方法
//参数:student,表示要插入到数据库的数据
//返回值:int,表示执行insert操作后的,影像数据库的行数
int insertStudent(Student student);
//更新方法
int updateStudent(Student student);
//删除方法
int deleteStudent(int id);
}
(8) 编写 Dao 接口 Mapper 映射文件 StudentDao.xml
要求:
- 在 dao 包中创建文件 StudentDao.xml
- 要 StudentDao.xml 文件名称和接口 StudentDao 一样,区分大小写的一样。
<?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">
<!--
namespace:必须有值,自定义的唯一字符串
推荐使用:dao 接口的全限定名称
--> <mapper namespace="com.zep.dao.StudentDao">
<!--
<select>: 查询数据, 标签中必须是 select 语句
id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称,
使用名称表示要执行的 sql 语句
resultType: 查询语句的返回结果数据类型,使用全限定类名
-->
<select id="selectStudents" resultType="com.zep.domain.Student">
<!--要执行的 sql 语句-->
select id,name,email,age from student order by id
</select>
<!--
select:表示查询操作。
id:你要执行的sql语句的唯一标识,mybatis会使用这个id的值找到要执行的sql语句。
可以自定义,但是要求你使用接口中的方法名称。
resultType:表示结果类型,是sql语句执行后得到的ResultSet,遍历这个ResultSet的到的java对象的类型
值写的是类型的全限定名称
-->
<!--
插入操作,#{id},#{name},#{email},#{age}中的id,name,email,age是student实体类中的属性名称
-->
<insert id="insertStudent">
insert into student(id,name,email,age) values(#{id},#{name},#{email},#{age})
</insert>
<update id="updateStudent">
update student set age = #{age} where id=#{id}
</update>
<delete id="deleteStudent">
delete from student where id=#{studentId}
</delete>
</mapper>
<!--
sql映射文件:写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是约束文件的名称,扩展名是dtdd的。
2.约束文件的作用:用来限制,检查在当前文件中出现的标签和属性,必须符合mybatis的要求
3.mapper 是当前文件的跟标签,必须有
namespace:叫做命名空间,唯一值,可以是自定义的字符串
要求你使用dao接口的全限定名称。
4.在当前文件中,可以使用特定的标签,表示数据库的特定操作
<select>:表示执行查询操作
<update>:表示执行更新数据库的操作,就是在<update>标签中,写的是update sql语句
<insert>:表示插入,放的是insert语句
<delete>:表示删除,执行的delete语句
-->
(9) 创建 MyBatis 主配置文件
项目 src/main 下创建 resources 目录,设置 resources 目录为 resources root
创建主配置文件:名称为 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>
<!--mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--
配置 mybatis 环境:数据库的连接信息
default:必须和某个environment标签中的id值一样。
告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
-->
<environments default="mysql">
<!--id:数据源的名称,一个唯一值,可自定义,用来表示环境的名称-->
<environment id="mysql">
<!--
配置事务类型:
使用 JDBC 事务(使用 Connection 的提交和回滚)
type:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--数据源 dataSource:创建数据库 Connection 对象
type: POOLED 使用数据库的连接池
-->
<dataSource type="POOLED">
<!--
连接数据库的四个要素:driver,user,username,password名字是固定的,不能自定义
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--
告诉 mybatis 要执行的 sql 语句的位置
sql mapper(sql映射文件)的位置
一个mapper标签指定一个文件的位置。
位置是从类路径开始的路径信息。类路径:target/classes(类路径)
-->
<mapper resource="com/zep/dao/StudentDao.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 根标签
-->
(10) 创建测试类 MyBatisTest
src/test/java/com/zep/ 创建 MyBatisTest.java 文件
package com.zep;
import com.zep.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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMybatis {
@Test
public void testSelect() throws IOException {
// 1.定义mybatis主配置文件的名称,从类路径的跟开始,也就是(target/classes)
String config = "mybatis.xml";
// 2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
// 3.创建SqlSessionFactoryBulider对象
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 sqlId = "com.zep.dao.StudentDao"+ "." +"selectStudents";
// 7.执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
// 8.输出结果
// studentList.forEach(student -> System.out.println(student));
for (Student student : studentList) {
System.out.println("查询到的学生=" + student);
}
// 9.关闭SqlSession对象
sqlSession.close();
}
//测试方法,测试功能
@Test
public void testInsert() throws IOException {
//1.mybatis 主配置文件
String config = "mybatis.xml";
//2.读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建 SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取 SqlSession
SqlSession session = factory.openSession();
//5.创建保存数据的对象
Student student = new Student();
student.setId(1005);
student.setName("张丽");
student.setEmail("[email protected]");
student.setAge(20);
//6.执行插入 insert
int rows = session.insert(
"com.zep.dao.StudentDao.insertStudent", student);
//7.提交事务
session.commit();
System.out.println("增加记录的行数:" + rows);
//8.关闭 SqlSession
session.close();
}
@Test
public void testUpdate() throws IOException {
//1.mybatis 主配置文件
String config = "mybatis.xml";
//2.读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建 SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取 SqlSession
SqlSession session = factory.openSession();
//5.创建保存数据的对象
Student student = new Student();
student.setId(1005);//要修改的 id
student.setAge(30); //要修改的年龄值
//6.执行更新 update
int rows = session.update(
"com.zep.dao.StudentDao.updateStudent", student);
//7.提交事务
session.commit();
System.out.println("修改记录的行数:" + rows);
//8.关闭 SqlSession
session.close();
}
@Test
public void testDelete() throws IOException {
//1.mybatis 主配置文件
String config = "mybatis.xml";
//2.读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建 SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取 SqlSession
SqlSession session = factory.openSession();
//5.删除的 id
int id = 1005;
//6.执行删除 delete
int rows = session.delete(
"com.zep.dao.StudentDao.deleteStudent",id);
//7.提交事务
session.commit();
System.out.println("修改记录的行数:"+rows);
//8.关闭 SqlSession
session.close();
}
}
(11)运行结果如下:
1.3总结
1.4开发中常见的问题
- 读取不到dao文件夹下的StudentDao.xml文件
原因:target目录下确实不存在StudentDao.xml文件,所有读取不到
解决方案:在pom.xml文件中加入以下配置:
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
2. 读取不到resources文件夹下的mybatis.xml文件
原因:没有将resources文件夹标记为Test resources 根
解决方案:
注意:如果以上两种方法尝试后,仍然存在读取不到文件的问题,则使用以下方法
还不行的话,重构工程:
还不行就删除缓存,重启IDEA:
最后还是不行的话,暴力解决,相当于手动读取:
直接将项目目录下的StudentDao.xml文件复制粘贴到classes目录下对应的位置
把mybatis.xml复制粘贴到classes目录下
- 目录结构中找不到target文件夹
解决方案:
- pom.xml文件中的依赖没有导入成功
解决方案:手动重新导入即可
重新导入成功后就能看见对应的jar包了