当Java程序需要与数据库进行通信时,需要借助JDBC才能实现这个过程,接下来我们看看这个过程。
JDBC实现和数据库的通信
public static void main(String[] args) throws Exception {
//读取数据库的配置文件
try (InputStream in = Demo.class.getClassLoader().getResourceAsStream("db.properties")) {
Properties properties = new Properties();
properties.load(in);
String driver = properties.getProperty("drive_name");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
//加载MySQL驱动
Class.forName(driver);
//创建连接
try (Connection connection = DriverManager.getConnection(url, username, password)) {
//创建具有高安全性的SQL语句
try (PreparedStatement preparedStatement = connection.prepareStatement("select * from student where id=?")) {
//设置参数
preparedStatement.setInt(1, 1);
//发送SQL到MySQL执行并获取结果
try (ResultSet resultSet = preparedStatement.executeQuery()) {
//迭代结果集合
while (resultSet.next()) {
//获取列的值
System.out.println(resultSet.getInt("id"));
System.out.println(resultSet.getString("name"));
}
}
}
}
}
}
上面的示例展示了一个查询操作,但从这些简单的代码中却可以看出来很多JDBC的缺点:
- 数据库连接频繁的创建和释放,浪费资源,降低了性能
- SQL语句硬编码在Java代码中,导致SQL维护起来比较困难,需要修改代码才能完成
- 如果改变代码中的SQL,对于SQL中参数类型和数量的变化都会导致维护成本升高,需要修改分散在代码中的类似【setInt】的操作或者是【getString】操作
- 查询类返回的结果不友好,无法直接映射为POJO类,增加额外的处理操作
- 大量的重复代码,可读性差,代码臃肿
虽然有DBCP
和C3P0
这样的数据库连接池管理解决方案和DBUtil
这样的工具包,但是仍不能完全解决上述的种种问题。
初识Mybatis
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
来自Mybatis官方文档 https://mybatis.org/mybatis-3/zh/index.html
从官方对Mybatis的定义,可以看出来Mybatis是一个非常优秀的ORM框架,可以几乎避免所有使用JDBC编程带来的缺点,通过简单的配置即可实现对SQL返回结果和POJO之间的映射等等。我们在来看一看使用Mybaits实现同样的查询是怎么样的?
Mybatis 的核心结构
Mybatis 实现和数据库的通信
public static void main(String[] args) throws Exception {
//读取Mybatis配置文件信息
try(InputStream stream =Resources.getResourceAsStream("mybatis-config.xml")) {
//创建SqlSession工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);
//生成SqlSession实例
try (SqlSession session = factory.openSession()) {
//使用SqlSession完成查询操作
List<Student> students = session.selectList("com.vitamin.mybatis.mapper.GetStudents", 1);
for (Student student : students) {
System.out.println(student);
}
}
}
}
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>
<!-- 设置properties文件的位置 -->
<properties resource="db.properties" />
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${drive_name}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- 映射配置文件的存储位置 -->
<mappers>
<mapper resource="StudentMapper.xml"></mapper>
</mappers>
</configuration>
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="com.vitamin.mybatis.mapper">
<!-- 查询类SQL语句标签 需要有唯一的id,入参类型和返回值类型 -->
<select id="GetStudents" parameterType="int" resultType="com.vitamin.mybatis.Student">
select * from student where id=#{id}
</select>
</mapper>
上面的示例通过对比JDBC实现的同时也展示了Mybatis的简单用法,Mybatis在代码的实现上将硬编码的内容全部都移动到了配置的Mapper文件中,提高了SQL编写的灵活性并且使用了数据库连接池管理连接,提高了资源利用率和性能。
Mybatis 和 Hibernate 对比
我相信在了解Mybatis之后,必然会碰见另一个鼎鼎大名的ORM框架 Hibernate,同样作为ORM他们之间有什么区别呢?来对比一下:
- Mybatis 相对于 Hibernate 而言属于一个半自动的ORM框架,因为使用Mybatis需要我们手动维护SQL语句。但这也是Mybatis的优点,提高了SQL的灵活性,方便后续优化SQL。而 Hibernate 却可以根据对象自动映射为SQL语句,不易维护,SQL优化的空间比较小。
- Mybatis 需要针对不同的数据库编写不同的SQL,由于手动维护的SQL不能满足所有的数据库。Hibernate 则会根据对象模型针对不同的数据库生成不同的SQL
- Hibernate 比较复杂,庞大,学习时间长 ,但功能却很强大。而Mybatis则相对轻量一些。
无论是 Mybatis 也好,Hibernate 也罢都有适合自己发挥特长的场景,具体何时该使用何种ORM取决于所依赖的场景。
总结
上面的各小节对Mybatis的使用只为了快速入门,简单且直观。但要想在项目中使用Mybatis,往往需要使用更高级的内容,这部分在后续的文章中会有提及。好了,到这里本篇结束了,快把Mybatis使用起来吧。