在简单的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 ...
随机推荐
- 西柚考勤系统——alpha1
这个作业属于哪个课程 http://edu.cnblogs.com/campus/xnsy/GeographicInformationScience 这个作业的要求在哪里 https://www.cn ...
- 《HelloGitHub》第 46 期
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...
- 同一个环境同时使用python2和python3的方法
1.首先安装好p2和p3,配置好环境变量.在CMD内执行python返回版本号,返回结果根据配置的环境变量而定,如果p2的环境变量配置在前面,则返回p2的版本号,反之则p3 2.然后把各版本目录下的p ...
- MAVEN报错Cannot access alimaven / idea data注解不好使
BUG 记录 报错页面的代码和截图: Cannot access alimaven (maven.aliyun.com/nexus/conte…..... 解决方法: 报错页面的代码和截图: JAR ...
- Windows版Redis主从配置
一.下载 从github上下载Redis的zip包,地址:https://github.com/MicrosoftArchive/redis/releases Redis本身不支持windows,这是 ...
- 004-OSI参考模型和分层思想
OSI参考模型 应用层 所有能产生网络流量的程序 表示层 在传输之前是否进行加密或者压缩处理 涉及安全问题 会话层 Session 是建立在传输层之上,利用传输层提供的服务,使应用建立和维持会话,并能 ...
- node + multer存储element-ui上传的图片
说明 element-ui的Upload组件可以帮助我们上传我们的图片到我们的服务器,可以使用action参数上传图片,也可以使用http-request自定义上传方式.这里我们使用自定义的方式上传. ...
- React 函数生命周期
React 函数生命周期基础 1 ,概念 在组件创建.到加载到页面上运行.以及组件被销毁的过程中,总是伴随着各种各样的事件,这些在组件特定时期,触发的事件,统称为组件的生命周期:* 2,组件生命周 ...
- Go语言标准库之net/http
Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现. net/http介绍 Go语言内置的net/http包提供了HTTP客户端和服务端的实现. HTTP协议 超文本传输协 ...
- re模块 常用函数
1. findall() 函数 find('正则表达式',‘待匹配的字符串’) #返回匹配到字符串,并存放在列表中 详解见:https://www.cnblogs.com/nbk-zyc/p/1111 ...