本文来自【优锐课】——抽丝剥茧,细说架构那些事。java
ORM(对象关系映射)是用于数据库编程的出色工具。只需一点经验和Java注释的强大功能,咱们就能够相对轻松地构建复杂的数据库系统并利用生产力。关系数据库是大多数商业应用程序的主体。关系模型和面向对象的模型之间的不匹配老是很难映射。ORM工具以一种能够将对象映射到数据库中的方式为咱们提供了帮助,就好像咱们再也不使用关系模型的记录而是使用面向对象模型中的对象同样。这改变了JDBC编程的整个范例。mysql
在使用Java编写普通的JDBC代码时,你将赞成它确实笨拙而费力,几乎每次咱们向数据库发出CRUD请求时,一遍又一遍地编写相同的代码。如今,想象一下若是咱们能够编写以下内容,世界将会如何:程序员
1 MyPojo hmm=new MyPojo(); 2 MagicWand wave=MagicWand.getInstance(); 3 wave.save(hmm);
并保留没有常规样板代码的POJO,而在咱们与JDBC中的数据库交互时,咱们不可避免地须要用某种方式来编写。你怎么看?可能?好吧,是的。魔术棒是Java中的ORM(对象关系映射)工具。市场上有不少可用的ORM工具。Hibernate是其中之一,而且很是有效且可靠。在本文中,咱们将其做为实例引用示例代码。sql
JDBC须要大量的代码来管理链接并维护各类规则,以确保咱们的应用程序不会泄漏任何资源。 查看如下相对较大的JDBC代码,以获取员工记录的列表。数据库
1 public List<Employee> getEmployees() { 2 List<Employee> list = new ArrayList<>(); 3 Connection con = null; 4 PreparedStatement pstmt = null; 5 try { 6 Class.forName("com.mysql.jdbc.Driver"); 7 con = DriverManager.getConnection("jdbc:mysql://localhost/minilibrary", "user1", "secret"); 8 pstmt = con.prepareStatement("SELECT * FROM emp ORDER BY empId"); 9 ResultSet rs = pstmt.executeQuery(); 10 while (rs.next()) { 11 Employee emp = new Employee(); 12 emp.setEmpId(rs.getInt(1)); 13 emp.setName(rs.getString(2)); 14 emp.setPhone(rs.getString(3)); 15 emp.setEmail(rs.getString(4)); 16 emp.setSalary(rs.getFloat(5)); 17 emp.setDesignation(rs.getString(6)); 18 list.add(emp); 19 } 20 } catch (SQLException | ClassNotFoundException ex) { 21 Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, "Could not acquire record", ex); 22 throw new EmployeeException("Failed to retrieve employee from the database"); 23 } finally { 24 try { 25 if (pstmt != null) { 26 pstmt.close(); 27 } 28 if (con != null) { 29 con.close(); 30 } 31 } catch (SQLException ex) { 32 Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, null, ex); 33 } 34 } 35 return list; 36 }
尽管有各类各样的技术能够将其缩小到至关合适的大小,尤为是用于打开链接和记录问题的样板部分,可是从ResultSet中提取对象实例的主要逻辑仍然是相同的。当对象包含对其余对象或对象集合的引用时,状况就更糟了。编程
Hibernate减轻了JDBC编程的许多麻烦,并以更合理的方式解决了这个问题,或者咱们应该说面向对象的方式。咱们能够从选择的表列中建立一个POJO,并将其保存在数据库中。Hibernate直接支持类之间的继承和其余面向对象的关系。咱们可使用这些关系机制在关系数据库级别创建一对一,一对多,多对多映射。在Java注释@Entity的帮助下,建立实体很简单。@Id表示empId是数据库的主键。session
1 @Entity 2 public class Employee { 3 @Id 4 private int empId; 5 private String empName; 6 ... 7 }
hibenate的关键在于配置设置,能够在一般称为hibernate.cfg.xml的XML文件中完成配置。也能够经过Java代码设置此配置设置,以下所示。架构
1 public class HibernateUtil { 2 3 private static final SessionFactory sessionFactory; 4 private static final ServiceRegistry serviceRegistry; 5 static { 6 try { 7 Configuration config = getConfiguration(); 8 serviceRegistry = new ServiceRegistryBuilder().applySettings( 9 config.getProperties()).buildServiceRegistry(); 10 config.setSessionFactoryObserver(new SessionFactoryObserver() { 11 private static final long serialVersionUID = 1L; 12 13 14 15 @Override 16 public void sessionFactoryCreated(SessionFactory factory) { 17 } 18 19 20 21 @Override 22 public void sessionFactoryClosed(SessionFactory factory) { 23 ServiceRegistryBuilder.destroy(serviceRegistry); 24 } 25 }); 26 sessionFactory = config.buildSessionFactory(serviceRegistry); 27 } catch (Throwable ex) { 28 System.err.println("Initial SessionFactory creation failed." + ex); 29 throw new ExceptionInInitializerError(ex); 30 } 31 } 32 public static Session openSession() { 33 return sessionFactory.openSession(); 34 } 35 36 37 38 private static Configuration getConfiguration() { 39 Configuration cfg = new Configuration(); 40 cfg.addAnnotatedClass(Employee.class ); 41 cfg.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver"); 42 cfg.setProperty("hibernate.connection.url","jdbc:mysql://localhost/hr"); 43 cfg.setProperty("hibernate.connection.username", "user1"); 44 cfg.setProperty("hibernate.connection.password", "secret"); 45 cfg.setProperty("hibernate.show_sql", "true"); 46 cfg.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLSQLDialect"); 47 cfg.setProperty("hibernate.hbm2ddl.auto", "update"); 48 cfg.setProperty("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider"); 49 cfg.setProperty("hibernate.current_session_context_class", "thread"); 50 return cfg; 51 } 52 }
设置好配置属性后,咱们就能够开始了。如今让咱们重写getEmployees函数的JDBC版本以获取雇员列表。app
1 public List<Employee> getEmployees(){ 2 Session s=HibernateUtil.openSession(); 3 s.beginTransaction(); 4 List<Employee> list=s.createQuery("FROM Employee").list(); 5 s.getTransaction().commit(); 6 s.close(); 7 return list; 8 }
并非那么简单,清晰,并说明了为何任何JDBC程序员都在数据库编程中使用Hibernate或任何其余ORM工具。框架
不,不,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架构思惟导图,分享给你们对照知识点参考学习。