一、什么是框架
- 它是我们软件开发中的一套解决方案,不同的框架解决不同的问题
使用框架的好处:
- 框架封装了很多的细节,是开发者可以使用极简的方式实现功能,大大提高开发效率
二、三层架构
2.1 表现层
- 用于展示数据
2.2 业务层
- 处理业务需求
2.3 持久层
- 和数据库交互
三、持久层技术的解决方案
3.1 JDBC技术
Connection
PreparedStatement
ResultSet
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager .getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root", "root");
//定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//上边使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作。
3.2 Spring的JdbcTemplate
- Spring中对JDBC的简单封装
3.3 Apache的DBUtils
- 与Spring的
JdbcTemplate
类似,也是对Jdbc的简单封装
3.4 注意
以上都不是框架
- JDBC是规范
- Spring的
JdbcTemplate
和Apache的DBUtils
都只是工具类
3.5 JDBC问题的分析
- 数据库连接创建、释放频繁会造成西戎资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
- Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
- 使用
preparedStatement
向占位符传参数存在硬编码,因为sql语句的where
条件不一定,有多有少,修改sql还要修改代码,系统不易维护 - 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
四、MyBatis概述
- MyBatis是一个持久层的框架,是使用java编写的。
- 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程。
它使用了ORM思想实现了结果集的封装。
ORM:Object Relational Mapping 对象关系映射
- 将数据库的表及字段名和实体类及属性对应起来。
| user(表) | User(实体类) |
| :--------: | :------------: |
| id | userId |
| user_name | userName |- 最好将实体类中的属性和数据库的字段名保持一致
| user(表) | User(实体类) |
| :--------: | :------------: |
| id | id |
| user_name | user_name |
五、MyBatis入门(基于xml配置文件)
5.1 环境搭建
- 前提
5.1.1 创建Maven工程并导入依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ruki</groupId> <artifactId>day01_eesy_01mybatis</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <!-- mybatis依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!-- mysql依赖 --> <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.12</version> </dependency> <!-- 单元测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
5.1.2 创建实体类和dao接口
- 准备数据库表
创建实体类,
User
package com.ruki.domain; import java.io.Serializable; import java.util.Date; public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
创建dao,
IUserDao
package com.ruki.dao; import com.ruki.domain.User; import java.util.List; /** * 用户的持久层接口 */ public interface IUserDao { /** * 查询所有的操作 * @return list */ List<User> findAll(); }
5.1.3 创建映射配置文件(IUserDao.xml)
要求:
- 创建位置:必须和持久层接口在相同的包中
- 名称:必选以持久层接口名称命名文件名,扩展名为
.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">
<!-- dao的全限定类名-->
<mapper namespace="com.ruki.dao.IUserDao">
<!-- 配置查询所有
id: 方法的名称
resultType:必须说清楚返回的类型是什么,不然查出来不知道以什么类型返回
-->
<select id="findAll" resultType="com.ruki.domain.User">
select * from user
</select>
</mapper>
mapper
namespace
:限定标签中的内容去哪里找。- <font color="red">全限定类名</font>:如标签体中的
findAll()
方法去com.ruki.dao
包下的IUserDao
中找
- <font color="red">全限定类名</font>:如标签体中的
select
id
:方法名resultType
:返回结果的类型。- <font color="red">全限定类名</font>:规定以具体包下某个类的类型返回。
- 标签体:sql语句
5.1.4 创建MyBatis主配置文件(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/mybatis01"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/ruki/dao/IUserDao.xml" />
</mappers>
</configuration>
configuration
environments
default
:mysql
environment
id
:mysql
transactionManager
:事务管理对象type
:JDBC
dataSource
type
:POOLED
property
:数据库连接的4个基本信息name
:- driver
- url
- username
- password
value
mappers
mapper
resource
:告知mybatis映射配置文件的位置
5.2 环境搭建的注意事项
创建
IUserDao.xml
和IUserDao.java
,名称是为了和之前的保持一致。- 在MyBatis中,它把持久成的操作接口名称和映射文件也叫做
Mapper
IUserDao
和IUserMapper
是一样的
- 在MyBatis中,它把持久成的操作接口名称和映射文件也叫做
在idea中创建目录的时候,和创建包是不一样的
- 包在创建时:
com.ruki.dao
是三级结构 - 目录在创建时:
com.ruki.dao
是一级目录
- 包在创建时:
- MyBatis的映射配置文件位置必须和dao接口的包结构相同
- 映射配置文件的
mapper
标签和namespace
属性的取值必须是dao接口的全限定类名 - 映射配置文件的操作配置(
select
),id
属性的取值必须是dao接口的方法名
- 遵从了第3、4、5点后,在之后的开发中就无需再写dao的实现类(xxDaoImpl)
六、测试步骤
- 读取配置文件
- 创建
SqlSessionFactory
工厂 - 创建
SqlSession
创建Dao接口的代理对象
- 创建代理对象
- 在代理对象中调用
selectList
- 执行Dao中的方法
- 释放资源
package com.ruki.test;
import com.ruki.dao.IUserDao;
import com.ruki.domain.User;
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 MyBatisTest {
public static void main(String[] args) throws IOException {
//1. 读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2. 创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
//3. 使用工厂生产一个SqlSession对象
SqlSession session = sessionFactory.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入门(基于注解)
将
IUserDao.xml
删除,在dao接口的方法上使用@Select
注解,并且指定sql语句@Select("select * from user")
package com.ruki.dao; import com.ruki.domain.User; import org.apache.ibatis.annotations.Select; import java.util.List; /** * 用户的持久层接口 */ public interface IUserDao { /** * 查询所有的操作 * @return list */ @Select("select * from user") List<User> findAll(); }
在
SqlMapConfig.xml
中的mapper
配置时,使用<font color="red">class</font>属性指定dao接口的全限定类名,而不是之前的resource
<mappers> <!--<mapper resource="com/ruki/dao/IUserDao.xml" />--> <mapper class="com.ruki.dao.IUserDao" /> </mappers>