在简单的JDBC程序中使用ORM工具
本文来自【优锐课】——抽丝剥茧,细说架构那些事。
ORM(对象关系映射)是用于数据库编程的出色工具。只需一点经验和Java注释的强大功能,我们就可以相对轻松地构建复杂的数据库系统并利用生产力。关系数据库是大多数商业应用程序的主体。关系模型和面向对象的模型之间的不匹配总是很难映射。ORM工具以一种可以将对象映射到数据库中的方式为我们提供了帮助,就好像我们不再使用关系模型的记录而是使用面向对象模型中的对象一样。这改变了JDBC编程的整个范例。
它在哪里适合JDBC
在使用Java编写普通的JDBC代码时,你将同意它确实笨拙而费力,几乎每次我们向数据库发出CRUD请求时,一遍又一遍地编写相同的代码。现在,想象一下如果我们可以编写如下内容,世界将会如何:
MyPojo hmm=new MyPojo();
MagicWand wave=MagicWand.getInstance();
wave.save(hmm);
并保留没有常规样板代码的POJO,而在我们与JDBC中的数据库交互时,我们不可避免地需要用某种方式来编写。你怎么看?可能?好吧,是的。魔术棒是Java中的ORM(对象关系映射)工具。市场上有很多可用的ORM工具。Hibernate是其中之一,并且非常有效且可靠。在本文中,我们将其作为实例引用示例代码。
JDBC方式
JDBC需要大量的代码来管理连接并维护各种规则,以确保我们的应用程序不会泄漏任何资源。 查看以下相对较大的JDBC代码,以获取员工记录的列表。
public List<Employee> getEmployees() {
List<Employee> list = new ArrayList<>();
Connection con = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost/minilibrary", "user1", "secret");
pstmt = con.prepareStatement("SELECT * FROM emp ORDER BY empId");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
Employee emp = new Employee();
emp.setEmpId(rs.getInt(1));
emp.setName(rs.getString(2));
emp.setPhone(rs.getString(3));
emp.setEmail(rs.getString(4));
emp.setSalary(rs.getFloat(5));
emp.setDesignation(rs.getString(6));
list.add(emp);
}
} catch (SQLException | ClassNotFoundException ex) {
Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, "Could not acquire record", ex);
throw new EmployeeException("Failed to retrieve employee from the database");
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
return list;
}
尽管有各种各样的技术可以将其缩小到相当合适的大小,尤其是用于打开连接和记录问题的样板部分,但是从ResultSet中提取对象实例的主要逻辑仍然是相同的。当对象包含对其他对象或对象集合的引用时,情况就更糟了。
输入ORM
Hibernate减轻了JDBC编程的许多麻烦,并以更合理的方式解决了这个问题,或者我们应该说面向对象的方式。我们可以从选择的表列中创建一个POJO,并将其保存在数据库中。Hibernate直接支持类之间的继承和其他面向对象的关系。我们可以使用这些关系机制在关系数据库级别建立一对一,一对多,多对多映射。在Java注释@Entity的帮助下,创建实体很简单。@Id表示empId是数据库的主键。
@Entity
public class Employee {
@Id
private int empId;
private String empName;
...
}
hibenate的关键在于配置设置,可以在通常称为hibernate.cfg.xml的XML文件中完成配置。也可以通过Java代码设置此配置设置,如下所示。
public class HibernateUtil {
private static final SessionFactory sessionFactory;
private static final ServiceRegistry serviceRegistry;
static {
try {
Configuration config = getConfiguration();
serviceRegistry = new ServiceRegistryBuilder().applySettings(
config.getProperties()).buildServiceRegistry();
config.setSessionFactoryObserver(new SessionFactoryObserver() {
private static final long serialVersionUID = 1L;
@Override
public void sessionFactoryCreated(SessionFactory factory) {
}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
ServiceRegistryBuilder.destroy(serviceRegistry);
}
});
sessionFactory = config.buildSessionFactory(serviceRegistry);
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static Session openSession() {
return sessionFactory.openSession();
}
private static Configuration getConfiguration() {
Configuration cfg = new Configuration();
cfg.addAnnotatedClass(Employee.class );
cfg.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver");
cfg.setProperty("hibernate.connection.url","jdbc:mysql://localhost/hr");
cfg.setProperty("hibernate.connection.username", "user1");
cfg.setProperty("hibernate.connection.password", "secret");
cfg.setProperty("hibernate.show_sql", "true");
cfg.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLSQLDialect");
cfg.setProperty("hibernate.hbm2ddl.auto", "update");
cfg.setProperty("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider");
cfg.setProperty("hibernate.current_session_context_class", "thread");
return cfg;
}
}
设置好配置属性后,我们就可以开始了。现在让我们重写getEmployees函数的JDBC版本以获取雇员列表。
public List<Employee> getEmployees(){
Session s=HibernateUtil.openSession();
s.beginTransaction();
List<Employee> list=s.createQuery("FROM Employee").list();
s.getTransaction().commit();
s.close();
return list;
}
并不是那么简单,清晰,并说明了为什么任何JDBC程序员都在数据库编程中使用Hibernate或任何其他ORM工具。
如果ORM是解决方案,那么JDBC是一个问题吗?
不,不,JDBC完全可以。实际上,在某些情况下(例如常见的CRUD操作),某种类型的对象关系映射是适当的,而通过JDBC连接API进行直接访问的传统方法占据了上风。ORM为程序员提供了一层便利。这种便利是否会带来性能代价。嗯,有很多传闻证明了这种缺点(尽管我尚未测试),但是我相信使用ORM工具的缺点远大于缺点。他们之间没有战争。一个可以弥补另一个缺点。从较高的角度来看,我们可以说– JDBC API在数据库编程中可以独立运行,而ORM工具则不能。即使我们在代码中显然不使用JDBC API,ORM也会始终使用下面的JDBC API。因此,以某种方式问我们应该选择哪个是一个荒谬的问题?ORM位于你的应用程序和JDBC之间,从而提供了编程的面向对象模型和关系数据库模型之间缺少的链接。实际上,这个所谓的ORM与JDBC交互以最终与数据库对话。下图可能会进一步阐明该概念。

图1:休眠在Java应用程序中的作用
结论
可以从Java应用程序直接调用Hibernate,也可以通过另一个框架访问它。无论是Swing应用程序,Servlet,JSP页面还是有权访问数据库的任何其他Java应用程序,我们通常都使用它来为应用程序创建数据访问层或替换现有的数据访问层。其他的ORM工具(例如MyBatis)通过不同的API和访问机制执行类似的功能。总体而言,ORM尤其是Hibernate比此高级概述更强大,更深入。也许本文提供了第一手的见解,并引起了你的兴趣,以探索兔子洞的深度。
感谢阅读!最后奉上近期整理出来的一套完整的java架构思维导图,分享给大家对照知识点参考学习。


在简单的JDBC程序中使用ORM工具的更多相关文章
- mybatis由浅入深day01_1课程安排_2对原生态jdbc程序中问题总结
mybatis 第一天 mybatis的基础知识 1 课程安排: mybatis和springmvc通过订单商品 案例驱动 第一天:基础知识(重点,内容量多) 对原生态jdbc程序(单独使用jdbc开 ...
- 编写一个简单的 JDBC 程序
连接数据库的步骤: 1.注册驱动(只做一次) 2.建立连接(Connection) 3.创建执行SQL的语句(Statement) 4.执行语句 5.处理执行结果(ResultSet) 6.释放资源 ...
- 01.原生态jdbc程序中问题总结
1.数据库启动包配置到工程目录中(mysql5.1) mysql-connector-java-5.1.7-bin.jar 2.jdbc原生态操作数据库(程序) 操作mysql数据库 1 packag ...
- 最简单的jdbc程序
package cn.ytu.mybatis.jdbc; import java.sql.Connection; import java.sql.DriverManager; import jav ...
- 对原生态jdbc程序中问题总结
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...
- 简单ORM工具的设计和编写,自己项目中曾经用过的
http://www.cnblogs.com/szp1118/archive/2011/03/30/ORM.html 在之前的一个项目中自己编写了一个简单的ORM小工具,这次重新整理和重构了一下代码, ...
- 在VS中手工创建一个最简单的WPF程序
如果不用VS的WPF项目模板,如何手工创建一个WPF程序呢?我们来模仿WPF模板,创建一个最简单的WPF程序. 第一步:文件——新建——项目——空项目,创建一个空项目. 第二步:添加引用,Presen ...
- win32程序中简单应用mfc
今日写程序在win32中用CRect发现报错,突然想起来.要引入mfc库.想重新建立一个工程添加对mfc的支持.发现选项不能选.查资料后发现. 在win32程序中简单应用mfc库,只需要简单的引入&l ...
- Windows程序设计笔记(二) 关于编写简单窗口程序中的几点疑惑
在编写窗口程序时主要是5个步骤,创建窗口类.注册窗口类.创建窗口.显示窗口.消息环的编写.对于这5个步骤为何要这样写,当初我不是太理解,学习到现在有些问题我基本上已经找到了答案,同时对于Windows ...
随机推荐
- Maven的学习之路1
对于下列这段Maven的命令行有不懂之处,在zgmzyr的博客上得到了解释.非常感谢这位博友,写在自己的随笔上以便查看和修改. 1. 创建项目 $ mvn archetype:generate -Dg ...
- python实例:从excel读取股票代码,爬取股票信息写到代码后面的单元格中
关键词:爬虫.python.request.接口.excel处理 思路: 1.首先准备好excel文档,把股票代码事先编辑进去. 2.脚本读取文档,依次读出股票代码到指定站点发起请求获取股票信息 3. ...
- Android教程2020 - RecyclerView响应点击
本文介绍RecyclerView设置点击的方法.这里给出比较常见的使用方式. Android教程2020 - 系列总览 本文链接 前面我们已经知道如何用RecyclerView显示一列数据. 用户点击 ...
- http1.0、http1.x、http 2和https梳理
http1.0.http1.x.http 2和https梳理 Http1.x 线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制数目的请求会被阻塞 http1.0 缺陷:浏览器与服务器只保持 ...
- java内存模型梳理
java内存模型 内存模型和内存结构区别 它们是两个概念. 内存模型是和jvm多线程相关的. 内存结构是指的jvm内存结构. 内存模型的作用 内存模型简称JMM JMM是决定一个线程对共享变量的写入时 ...
- 关于远程办公,微软MVP 15年研发团队的经验分享
今天是2月5日,春节假期结束后的第三天了.为了能够应对来势汹汹的疫情,众多互联网企业纷纷开启了远程办公模式.不知道各团队前两天的远程办公效果如何,我们 Worktile 管理层在大年初四就开始讨论远程 ...
- DRF框架之Serializer序列化器的序列化操作
在DRF框架中,有两种序列化器,一种是Serializer,另一种是ModelSerializer. 今天,我们就先来学习一下Serializer序列化器. 使用Serializer序列化器的开发步骤 ...
- vue项目使用keep-alive
作用: 在vue项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜 ...
- 互联网那些事 | MQ数据丢失
本系列故事的所有案例和解决方案只是笔者以前在互联网工作期间的一些事例,仅供大家参考,实际操作应该根据业务和项目情况设计,欢迎大家留言提出宝贵的意见 背景 小王和小明分别维护分布式系统中A.b两个服务, ...
- TLS使用指南(一):如何在Rancher 2.x中进行TLS termination?
引 言 这是一个系列文章,我们将在本系列中探索Rancher使用TLS证书的不同方式.TLS,安全传输层协议,是用于保护网络通信的加密协议.它是目前已经弃用的安全套接层(SSL)的继任者. 你可以从本 ...