为了方便操作,我们在sjdwz_test数据库下建立一张表:
CREATE TABLE `t_student` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) DEFAULT NULL COMMENT '名字', `age` int(255) DEFAULT NULL COMMENT '年龄', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名字',
`age` int(255) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
数据如下:
实体类如下:
package com.sjdwz.db;import lombok.*;/** * @Description 数据库实体 * @Created by 随机的未知 */@Data@ToString@NoArgsConstructor@AllArgsConstructor@Builderpublic class Student { private Long id; private String name; private Integer age;}
package com.sjdwz.db;
import lombok.*;
/**
* @Description 数据库实体
* @Created by 随机的未知
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Student {
private Long id;
private String name;
private Integer age;
}
我们先来回顾一下JDBC操作数据库的代码:
package com.sjdwz.jdbc;import com.sjdwz.db.Student;import java.sql.*;import java.util.ArrayList;import java.util.List;/** * @Description JDBC操作数据库代码示例 * @Date 2023/12/14 * @Created by 随机的未知 sjdwz.com */public class JDBCMain { public static void main(String[] args) throws SQLException, ClassNotFoundException { //数据库连接地址 String url = "jdbc:mysql://localhost:3306/sjdwz_test"; String user = "root";//用户名 String password = "1234567";//密码 //1.注册数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取数据库连接对象Connection。 Connection conn = DriverManager.getConnection(url, user, password); //3.创建Sql语句对象Statement,填写SQL语句 PreparedStatement preparedStatement = conn.prepareStatement("select * from t_student where `name` = ?; "); //传入查询参数 preparedStatement.setString(1, "张三"); //4.执行SQL查询,返回结果集对象ResultSet ResultSet resultSet = preparedStatement.executeQuery(); List<Student> studentList = new ArrayList<>(); //5.循环解析结果集,获取查询用户list集合 while (resultSet.next()) { Student student = Student.builder() .id(resultSet.getLong("id")) .name(resultSet.getString("name")) .age(resultSet.getInt("age")) .build(); studentList.add(student); } //打印查询结果 System.out.println(studentList); //6.关闭连接,释放资源 resultSet.close();//关闭结果集对象 preparedStatement.close();//关闭Sql语句对象 conn.close();//关闭数据库连接对象 }}
package com.sjdwz.jdbc;
import com.sjdwz.db.Student;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
* @Description JDBC操作数据库代码示例
* @Date 2023/12/14
* @Created by 随机的未知 sjdwz.com
public class JDBCMain {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//数据库连接地址
String url = "jdbc:mysql://localhost:3306/sjdwz_test";
String user = "root";//用户名
String password = "1234567";//密码
//1.注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接对象Connection。
Connection conn = DriverManager.getConnection(url, user, password);
//3.创建Sql语句对象Statement,填写SQL语句
PreparedStatement preparedStatement = conn.prepareStatement("select * from t_student where `name` = ?; ");
//传入查询参数
preparedStatement.setString(1, "张三");
//4.执行SQL查询,返回结果集对象ResultSet
ResultSet resultSet = preparedStatement.executeQuery();
List<Student> studentList = new ArrayList<>();
//5.循环解析结果集,获取查询用户list集合
while (resultSet.next()) {
Student student = Student.builder()
.id(resultSet.getLong("id"))
.name(resultSet.getString("name"))
.age(resultSet.getInt("age"))
.build();
studentList.add(student);
//打印查询结果
System.out.println(studentList);
//6.关闭连接,释放资源
resultSet.close();//关闭结果集对象
preparedStatement.close();//关闭Sql语句对象
conn.close();//关闭数据库连接对象
运行截图如下:
这段代码主要有如下四点问题:
所以我们需要一个ORM框架,来解决这些痛点。我用的最多的ORM框架是MyBatis,我们就来从源码角度来分析它,看看MyBatis是怎么解决这些问题的。
项目结构截图如下:
在resources目录下创建mybatis-config.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="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!--数据库连接信息--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/sjdwz_test?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="1234567"/> </dataSource> </environment> </environments> <mappers> <!-- 加载sql映射文件--> <mapper resource="StudentMapper.xml"/> </mappers></configuration>
<?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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/sjdwz_test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234567"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载sql映射文件-->
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
在resources目录下创建StudentMapper.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="test"> <!-- id是指sql的唯一标识,resulttype是指返回值的类型--> <select id="findListByName" resultType="com.sjdwz.db.Student" parameterType="string"> select * from t_student where `name` = #{name}; </select></mapper>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<!-- id是指sql的唯一标识,resulttype是指返回值的类型-->
<select id="findListByName" resultType="com.sjdwz.db.Student" parameterType="string">
select * from t_student where `name` = #{name};
</select>
</mapper>
MyBatis操作数据库代码如下:
package com.sjdwz.mybatis;import com.sjdwz.db.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;/** * @Description Mybatis示例 * @Created by 随机的未知 */public class MybatisTest { public static void main(String[] args) throws IOException { //1.创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //2.SqlSessionFactoryBuilder对象创建工厂对象 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); //3.工厂对象Factory打开SqlSession会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.SqlSession会话对象执行SQL语句,findListByName(命名空间+查询语句唯一标识) List<Student> studentList = sqlSession.selectList("test.findListByName","张三"); //5.打印查询结果 System.out.println(studentList); //6.关闭sqlSession会话 sqlSession.close(); }}
package com.sjdwz.mybatis;
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;
* @Description Mybatis示例
public class MybatisTest {
public static void main(String[] args) throws IOException {
//1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//2.SqlSessionFactoryBuilder对象创建工厂对象
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//3.工厂对象Factory打开SqlSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.SqlSession会话对象执行SQL语句,findListByName(命名空间+查询语句唯一标识)
List<Student> studentList = sqlSession.selectList("test.findListByName","张三");
//5.打印查询结果
//6.关闭sqlSession会话
sqlSession.close();
在前文,使用JDBC存在四个问题,而Mybatis就解决了这四个问题。
第一个问题是结果集解析复杂,列名硬编码,sql变化导致解析代码变化,系统不易维护;
结果集解析复杂,列名硬编码,sql变化导致解析代码变化,系统不易维护
MyBatis编码中我们不需要进行结果集解析,只需要在编码时指定sql即可,MyBatis会给我们结果;
第二个问题是sql语句硬编码,数据库配置硬编码,难以维护;
sql语句硬编码,数据库配置硬编码,难以维护
数据库的配置和sql语句,我们写到了xml文件,解决了硬编码的问题
第三个问题是频繁连接、释放数据库资源,没有用到池化思想,系统性能不高;
频繁连接、释放数据库资源,没有用到池化思想,系统性能不高
MyBatis使用了池化思想,解决了这个问题;
第三个问题是prepareadStatement向占位符传参数存在硬编码,不易维护;
prepareadStatement向占位符传参数存在硬编码,不易维护
我们在配置文件标签上写明了参数,并在代码中传入,避免了占位符的硬编码,解决了此问题。
我们回顾了JDBC和MyBatis的编码方式,了解了JDBC编码存在的问题,并知道了MyBatis编码确实解决了这几个问题。
后面我们就来分析MyBatis源码了。
原文链接:https://www.cnblogs.com/nicaicai/p/18154248
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728