数据持化技术的发展演变(SQL、JDBC、mybatis)
环境配置
- jdk
- maven
- idea
- 公众号:关注软件科技管家回复idea2019
- idea配置jdk和maven
正文开始之前
问题:大家有没有学习过这两本书?
为了开发时的层次清晰和分工明确,现如今基本上都将web应用的开发分成了五个层级结构,分别是表示层(Presentation)、控制/中介层(Controller/Mediator)、领域层(Domain)、数据持久层(Data Persistence)和数据源层(Data Source)。
我们都知道,为了方便数据的存储和查询一般都是将数据存储在数据库中,我们我可以通过SQL的增删改查语句来操作数据库的所有记录。以我的理解,数据持久化就是将程序代码中对数据记录的各种操作体现在数据库中,下一次再去查询数据库的时候不会说查到的还是操作之前的数据。学习数据持久层之前,我们需要先来复习一下SQL语句。
1 简单SQL语句
1.1 查询
讲解SQL语句之前先演示如何使用Navicat导入SQL文件,创建表并添加记录。如果没有图形化操作软件的话可以使用dos窗口的命令导入https://blog.csdn.net/qq_37918817/article/details/81107433
SELECT 列名称 FROM 表名称;
查询所有的记录
SELECT * FROM singer;
倒序查询所有的记录
SELECT * FROM singer
ORDER BY id DESC;
1.2 新增
INSERT INTO 表名称 [列名称…]
VALUES (值…);
插入一条记录
INSERT INTO singer
VALUES(64,'张三',1,'/img/singerPic/1586091210109Sanna Nielsen.jpg','1984-11-27 00:00:00','平顶山','五音不全');
1.3 修改
UPDATE 表名称
SET 列名称 = 新值 [,列名称 = 新值,…]
[WHERE <条件>];
修改id为64的introduction为歌声甜美
UPDATE singer
SET introduction='歌声甜美'
WHERE id=64;
1.4 删除
DELETE FROM 表名称
[WHERE <条件>];
按照id删除一条记录
DELETE FROM singer
WHERE id=64;
1.5 多表查询
SELECT *
FROM singer sr INNER JOIN song sg
ON sr.id = sg.singer_id
WHERE sr.name LIKE '王%'
ORDER BY sr.id DESC;
工程创建
创建一个project
创建两个maven的module分别是jdbc_test和mybatis_test创建一个Spring Initializr模块
2 JDBC
为什么需要数据持久化技术?每次修改数据库的时候直接使用SQL语句不就可以了?想象一下数据库就像是一台老式按键电视机,你家的沙发离这台电视机的距离不近(当然距离取决于个人家庭情况)。各种CRUD操作就像是你父母的节目需求,你正在看《巴啦啦小魔仙》,你家父皇来了想看《谭谈交通》,你家母后来了想要看《爱情保卫战》,过了一会你家父皇又想看《金牌调解》……你是不是就需要来回跑到电视前面使用按钮换台,这时候有人问你有个东西叫遥控器,他可以在十米范围内随意换台,你说你用不用?
2.1 什么是JDBC
JDBC就是Java数据库连接(Java Database Connectivity)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。jdbc是sun公司为了在Java语言中提供对数据库访问的支持,而提供的一套用于访问数据库的标准Java类库。我们通常说的JDBC是面向关系型数据库的,今天讲解的所有持久层框架也是以关型数据库为例
2.2 什么是jar和maven
之前java web的学习涉及到jar包也就是 Java Archive File文件,jar包其实是一种zip格式的文件,也就是压缩包它里面的内容就是Java代码,在项目的编写阶段导入jar包就可以使用里面提供的方法。不要认为jar包很是神秘,其实自己也可以创建一个jar包,只需要将写好的Java代码打成jar包再导入即可使用里面定义的方法。就好比你把一首歌的MP3文件放在压缩包发给你的朋友,他解压缩之后就可以听了。jar包参考博客
maven风格的项目,把所有的jar包都放在了本地"仓库“ 里,然后哪个项目需要用到这个jar包,只需要给出jar包的名称和版本号就行了(也就是常说的坐标),这样就实现了jar包共享,避免每一个项目都单独引入jar包带来的麻烦。使用maven管理就相当于,直接发给你的朋友这首歌的链接。maven参考博客
查询依赖的网站:https://mvnrepository.com/
2.3 JDBC的使用
首先需要导入数据库连接依赖,这样才能将Java代码连接到数据库
<!--数据库连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>runtime</scope>
</dependency>
然后创建实体类,实体类中的字段与数据库中的列名一一对应,数据类型也是相对应的
private Integer id;
private String name;
private Integer sex;
private String pic;
private Date birth;
private String location;
private String introduction;
public Singer() {
}
public Singer(Integer id, String name, Integer sex, String pic, Date birth, String location, String introduction) {
this.id = id;
this.name = name;
this.sex = sex;
this.pic = pic;
this.birth = birth;
this.location = location;
this.introduction = introduction;
}
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 Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
@Override
public String toString() {
return "Singer{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
", pic='" + pic + '\'' +
", birth=" + birth +
", location='" + location + '\'' +
", introduction='" + introduction + '\'' +
'}';
}
因为后面使用jdbc操作会频繁的连接数据库,关闭数据库释放资源,于是将这两个部分抽取成工具类中的静态方法,直接调用
// 加载驱动并建立数据库驱动
public static Connection getConnection() throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/music";
String username = "root";
String password = "123456";
String driver = "com.mysql.jdbc.Driver";
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
// 关闭数据库连接,释放资源
public static void release(Statement statement, Connection conn) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet resultSet, Statement statement, Connection conn) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
release(statement, conn);
}
持久层CRUD的方法api和测试方法的测试
查询所有记录
/**
* 查询所有方法
* @return
*/
public ArrayList<Singer> selectAll() {
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
ArrayList<Singer> singers = new ArrayList<Singer>();
try {
// 获取数据库连接
conn = JDBCUtil.getConnection();
// 获得statement对象
statement = conn.createStatement();
//发送SQL语句
String sql = "select * from singer;";
System.out.println(sql);
resultSet = statement.executeQuery(sql);
// 处理查询结果
while (resultSet.next()) {
Singer singer = new Singer();
singer.setId(resultSet.getInt("id"));
singer.setName(resultSet.getString("name"));
singer.setSex(resultSet.getInt("sex"));
singer.setPic(resultSet.getString("pic"));
singer.setBirth(resultSet.getDate("birth"));
singer.setLocation(resultSet.getString("location"));
singer.setIntroduction(resultSet.getString("introduction"));
singers.add(singer);
return singers;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
JDBCUtil.release(statement, conn);
}
return null;
}
// 查询所有的
SingerDao singerDao = new SingerDao();
ArrayList<Singer> singers = singerDao.selectAll();
for (Singer singer : singers) {
System.out.println(singer);
}
按照id查询
/**
* 按id查询方法
* @return
*/
public Singer selectById(Integer id) {
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 获取数据库连接
conn = JDBCUtil.getConnection();
// 获得statement对象
statement = conn.createStatement();
//发送SQL语句
String sql = "select * from singer where id=" + id +";";
System.out.println(sql);
resultSet = statement.executeQuery(sql);
// 处理查询结果
while (resultSet.next()) {
Singer singer = new Singer();
singer.setId(resultSet.getInt("id"));
singer.setName(resultSet.getString("name"));
singer.setSex(resultSet.getInt("sex"));
singer.setPic(resultSet.getString("pic"));
singer.setBirth(resultSet.getDate("birth"));
singer.setLocation(resultSet.getString("location"));
singer.setIntroduction(resultSet.getString("introduction"));
return singer;
}
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
JDBCUtil.release(statement, conn);
}
return null;
}
// 按照id查询
SingerDao singerDao = new SingerDao();
Singer singer = singerDao.selectById(63);
System.out.println(singer);
新增
/**
* insert操作
* @param singer
* @return
*/
public boolean insert(Singer singer) {
Connection conn = null;
Statement statement = null;
try {
// 获取数据库连接
conn = JDBCUtil.getConnection();
// 获得statement对象
statement = conn.createStatement();
//发送SQL语句
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String birth = sdf.format(singer.getBirth());
String sql = "INSERT INTO singer" +
" VALUES("
+ singer.getId() + ",'"
+ singer.getName() + "',"
+ singer.getSex() + ",'"
+ singer.getPic() + "','"
+ birth + "','"
+ singer.getLocation() + "','"
+ singer.getIntroduction()
+ "');";
System.out.println(sql);
int num = statement.executeUpdate(sql);
if (num > 0) {
return true;
}
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
JDBCUtil.release(statement, conn);
}
return false;
}
// 插入语句测试
// 先创建一个singer对象
Singer singer = new Singer();
singer.setId(64);
singer.setName("张三");
singer.setSex(1);
singer.setPic("/img/singerPic/1586091210109Sanna Nielsen.jpg");
singer.setBirth(new Date());
singer.setLocation("平顶山");
singer.setIntroduction("五音不全");
// 调用业务方法
SingerDao singerDao = new SingerDao();
boolean insert = singerDao.insert(singer);
System.out.println(insert);
修改
/**
* update方法
* @param singer
* @return
*/
public boolean update(Singer singer) {
Connection conn = null;
Statement statement = null;
try {
// 获取数据库连接
conn = JDBCUtil.getConnection();
// 获得statement对象
statement = conn.createStatement();
//发送SQL语句
String sql = "update singer set introduction='"
+ singer.getIntroduction() + "' where id="
+ singer.getId() + ";";
System.out.println(sql);
int num = statement.executeUpdate(sql);
if (num > 0) {
return true;
}
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
JDBCUtil.release(statement, conn);
}
return false;
}
// 修改
Singer singer1 = new Singer();
singer1.setId(64);
singer1.setIntroduction("歌声甜美");
SingerDao singerDao = new SingerDao();
boolean update = singerDao.update(singer1);
System.out.println(update);
按照id删除
/**
* delete方法
* @param id
* @return
*/
public boolean delete(Integer id) {
Connection conn = null;
Statement statement = null;
try {
// 获取数据库连接
conn = JDBCUtil.getConnection();
// 获得statement对象
statement = conn.createStatement();
//发送SQL语句
String sql = "delete from singer where id=" + id +";";
System.out.println(sql);
int num = statement.executeUpdate(sql);
if (num > 0) {
return true;
}
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
JDBCUtil.release(statement, conn);
}
return false;
}
// 删除
SingerDao singerDao = new SingerDao();
boolean delete = singerDao.delete(64);
System.out.println(delete);
2.4 JDBC总结
使用JDBC进行CRUD的步骤:
- 导入数据库连接依赖(jar包)
- 创建实体类
- 创建工具类(连接数据库,释放资源)
- 接口api方法(crud方法)
- 测试,创建方法类的对象,使用对象调用方法完成数据持久化操作
3 mybatis
还以遥控器为例,假如说你家的客厅100平,之前的遥控的范围不够,你还是要走几步,现在人家又说了,最新款的遥控器可以支持15米,你说你换不换?
mybatis是一种优秀的ORM框架
3.1 什么是ORM?为什么是ORM不是JDBC?
ORM(Object Relational Mapping)即对象关系映射,是一种开发规范。将简单的java对象(pojo)和数据库表记录进行映射,使得表中的记录能和POJO一一对应。
JDBC的劣势:代码繁琐(sql语句的拼接发送接收),SQL拼接复杂且容易出错,耦合度太高(SQL语句硬编码到java程序,不利于后期的维护),性能问题。基于以上诸多问题,企业中的开发慢慢过度到了ORM框架,下面讲到的mybatis框架就是一个十分优秀的ORM框架
3.2 mybatis的使用
maven项目的第一步,导依赖
<!--mybatis的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--数据库连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
创建POJO类Singer
private Integer id;
private String name;
private Integer sex;
private String pic;
private Date birth;
private String location;
private String introduction;
使用lombok简化开发
<!--lombok简化实体类开发,如果之前没有下载过依赖的同名插件的话需要下载安装,然后重启一下idea-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<optional>true</optional>
</dependency>
创建jdbc.properties数据库连接配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/music
jdbc.username=root
jdbc.password=123456
创建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>
<!--加载配置文件-->
<properties resource="jdbc.properties"/>
<typeAliases>
<typeAlias type="com.xiaochen.domain.Singer" alias="singer"/>
</typeAliases>
<!--数据源环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="mapper/SingerMapper.xml"/>
</mappers>
</configuration>
创建mapper接口
/**
* 查询全部
* @Param void
* @return ArraryList<Singer>
*/
public ArraryList<Singer> queryAll();
/**
* 按id查
* @param id
* @return Singer
*/
public Singer queryById(Integer id);
/**
* 增
* @param singer
* @return boolean
*/
public boolean save(Singer singer);
/**
* 改
* @param singer
* @return boolean
*/
public boolean update(Singer singer);
/**
* 删
* @param id
* @return boolean
*/
public boolean delete(Integer id);
使用Spring整合mybatis先导入依赖
<!--spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
spring框架整合mybatis需要满足的四个条件
- mapper标签的namespace = 接口全限定名
- 接口方法名 = mapper字标签的id
- 接口方法参数类型 = mapper字标签的parameterType
- 接口方法返回值类型 = mapper字标签的resultType
满足条件即可使用框架底层逻辑完成之前JDBC的数据库连接,SQL语句发送等过程。现在按照四个条件构建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.xiaochen.mapper.SingerMapper">
<!--查所有-->
<select id="queryAll" resultType="singer">
select * from singer order by id desc ;
</select>
<!--条件查-->
<select id="queryById" parameterType="int" resultType="singer">
select * from singer where id = #{id};
</select>
<!--增-->
<insert id="save" parameterType="singer">
insert into singer values (#{id},#{name},#{sex},#{pic},#{birth},#{location},#{introduction});
</insert>
<!--改-->
<insert id="update" parameterType="singer">
update singer set introduction = #{introduction} where id = #{id};
</insert>
<!--删-->
<insert id="delete" parameterType="int">
delete from singer where id = #{id};
</insert>
</mapper>
测试类使用Junit进行测试
导依赖
<!--Junit测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
/**
* 查询操作
* @Param void
* @return
*/
@Test
public void queryTest() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
SingerMapper mapper = session.getMapper(SingerMapper.class);
ArrayList<Singer> singers = mapper.queryAll();
for (Singer singer : singers) {
System.out.println(singer);
}
session.close();
}
/**
* 条件查询操作
* @Param void
* @return
*/
@Test
public void queryByIdTest() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
SingerMapper mapper = session.getMapper(SingerMapper.class);
Singer singer = mapper.queryById(63);
System.out.println(singer);
session.close();
}
/**
* 插入操作
* @Param void
* @return
*/
@Test
public void saveTest() throws IOException {
Singer singer = new Singer();
singer.setId(64);
singer.setName("张三");
singer.setSex(1);
singer.setPic("/img/singerPic/1586091210109Sanna Nielsen.jpg");
singer.setBirth(new Date());
singer.setLocation("平顶山");
singer.setIntroduction("五音不全");
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
SingerMapper mapper = session.getMapper(SingerMapper.class);
boolean result = mapper.save(singer);
System.out.println(result);
queryTest();
session.close();
}
/**
* 更新操作
* @Param void
* @return
*/
@Test
public void updateTest() throws IOException {
Singer singer = new Singer();
singer.setId(64);
singer.setIntroduction("歌声甜美");
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
SingerMapper mapper = session.getMapper(SingerMapper.class);
boolean update = mapper.update(singer);
System.out.println(update);
queryTest();
session.close();
}
/**
* 删除操作
* @Param void
* @return
*/
@Test
public void deleteTest() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
SingerMapper mapper = session.getMapper(SingerMapper.class);
boolean result = mapper.delete(64);
System.out.println(result);
queryTest();
session.close();
}
3.3 mybatis总结
mybatis开发步骤:
- 导依赖
- 创建实体类
- 配置文件
- spring框架整合mybatis需要满足的四个条件
- mapper标签的namespace = 接口全限定名
- 接口方法名 = mapper字标签的id
- 接口方法参数类型 = mapper字标签的parameterType
- 接口方法返回值类型 = mapper字标签的resultType
- 按照条件创建接口和映射文件
- 测试类读取配置文件创建mapper对象,调用方法
4 mybatis与jdbc的逻辑相同处
将mybatis对标jdbc可以发现,使用流程大体上是一样的,导入数据库连接依赖,创建实体类,创建持久层api方法供测试调用(mybatis将SQL抽取成了映射文件),测试类调用api并完成相应的操作。
- 点赞
- 收藏
- 关注作者
评论(0)