码家

Web Platform, Cloud and Mobile Application Development

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

众所周知,关系数据类型一直是SQL的诟病之一。随着数据的越加多样化,各种数据类型向关系数据类型的转换更是困扰着大多数的SQL数据库用户。然而SQL数据库能经久不衰,它的优点也是不容否定的。如果鱼与熊掌可以兼得 — 在SQL数据库中实现NoSQL数据类型,那么一切岂不是变的非常美好?!

话说世间万物有一得必有一失,而在0和1的世界里这点体现的是更加明显。无模式NoSQL存储在拥有了一些列的优点同时,付出的也不可谓不多。而NoSQL运动的主要优势莫过于赐予人们数据持久层的多样化选择。通过NoSQL我们不必要再将所有数据都转化成关系数据模式。而今最大的挑战没过于每个领域系统中数据持久模型的选择及后续模型的紧密集合。有很多方法可以用于解决这个问题,通用的方法一般是Polyglot Peristence。下面我们来看一下如何通过Java、Spring、Hibernate和PostgreSQL将普通的SQL模型与key-value NoSQL模型紧密的集合起来。

本文涉及到一个简单的网络应用程序,这个程序使用了常规SQL及PostgreSQL的hstore类型的键值对。思想是将NoSQL混合进SQL中,而这个方法的好处则是可以在同一个数据存储中同时储存SQL和NoSQL类型数据。

在这个例子中将覆盖Java、Spring和Hibernate服务器技术,当然也可以通过RailsDjango及一些其他技术来实现。为了向Hibernate中添加对hstore的支持,更是特意的查询了“通过Hibernate向单一数据库行中储存PostgreSQL hstore类型键/值对”这篇文章。虽然编码内容不会在这里详谈,但是你可以通过GitHub repo for my demo project得到你想要的一切。

演示应用程序使用Maven来定义依赖性。Jetty的嵌入则是通过一个简单的ole Java用用程序开始。Spring则是通过Java Config中的main部分web部分database部分来配置。

客户端技术将会用到jQuery和Bootstrap,而客户端和服务器将会通过RESTful JSON服务进行严格分隔。整个客户端部分都会放在一个简单的ole HTML文件中。客户端与JSON之间将通过jQuery/Ajax实现通信,这点则是在Spring MVC Controller中得以声明。

言归正传,回到在SQL中实现NoSQL上来。虽然该应用程序存储的“Contacts”只有一个name属性,但是不妨碍它拥有“Contacts Methods”(比如,电话号码和电子邮箱地址)。“Contact Methods”是个非常好的无模式键值对列因为它避免了繁琐的替代选择:将这些信息放进一个单独的表或者尝试去建立一个包含所有可能存在的“Contact Methods”类。来让我们看一下简单的Contact类

  1. package com.jamesward.model; 
  2.  
  3. import net.backtothefront.HstoreUserType; 
  4. import org.hibernate.annotations.Type; 
  5. import org.hibernate.annotations.TypeDef; 
  6.  
  7. import javax.persistence.Column; 
  8. import javax.persistence.Entity; 
  9. import javax.persistence.GeneratedValue; 
  10. import javax.persistence.Id; 
  11. import java.util.HashMap; 
  12. import java.util.Map; 
  13.  
  14. @Entity 
  15. @TypeDef(name = "hstore", typeClass = HstoreUserType.class
  16. public class Contact { 
  17.  
  18.     @Id 
  19.     @GeneratedValue 
  20.     public Integer id; 
  21.  
  22.     @Column(nullable = false
  23.     public String name; 
  24.  
  25.     @Type(type = "hstore"
  26.     @Column(columnDefinition = "hstore"
  27.     public Map<String, String> contactMethods = new HashMap<String, String>(); 
  28.  

如果你熟知Hibernate/JPA的话,那么以上这些对于你来说都会非常的熟悉。而吸引你的陌生之处在于contactMethods对象的修饰 — Map<String, String>,并且还使用了PostgreSQL的hostore数据类型。为了正常运行,hostore数据的类型必须被定义以及columnDefinition集。这不得不再次感谢Jakub GluszeckiHstoreHelperHostoreUserTyper的整合,否则的话这一切都无法实现。

因为只是简单的Hibernate/JPA,剩下的就比较简单了。下面是做基本查询和修改的ContactService类

  1. package com.jamesward.service;  
  2.  
  3. import com.jamesward.model.Contact;  
  4. import org.springframework.stereotype.Service;  
  5. import org.springframework.transaction.annotation.Transactional;  
  6.  
  7. import javax.persistence.EntityManager;  
  8. import javax.persistence.PersistenceContext;  
  9. import javax.persistence.criteria.CriteriaQuery;  
  10.  
  11. import java.util.List;  
  12.  
  13. @Service 
  14. @Transactional 
  15. public class ContactServiceImpl implements ContactService {  
  16.  
  17.     @PersistenceContext 
  18.     EntityManager em;  
  19.  
  20.     @Override 
  21.     public void addContact(Contact contact) {  
  22.         em.persist(contact);  
  23.     }  
  24.  
  25.     @Override 
  26.     public List<Contact> getAllContacts() {  
  27.         CriteriaQuery<Contact> c = em.getCriteriaBuilder().createQuery(Contact.class);  
  28.         c.from(Contact.class);  
  29.         return em.createQuery(c).getResultList();  
  30.     }  
  31.       
  32.     public Contact getContact(Integer id) {  
  33.         return em.find(Contact.class, id);  
  34.     }  
  35.  
  36.     @Override 
  37.     public void addContactMethod(Integer contactId, String name, String value) {  
  38.         Contact contact = getContact(contactId);  
  39.         contact.contactMethods.put(name, value);  
  40.     }  
  41.       

在你了解它的工作机制后,我们要开始尝试在Heroku上面的演示了

如果你想在本地或者Heroku上运行这个应用程序,那么首先你必须提取源代码然后继续新建spring_hibernate_hstore_demo目录的工作:

  1. $ git clone https://github.com/jamesward/spring_hibernate_hstore_demo.git  
  2. $ cd spring_hibernate_hstore_demo  

在本地运行需要做的工作:

1. 通过新建到pssql上的连接来允许PostgreSQL数据库对hstore的支持:

  1. $ psql -U username -W -h localhost database 

2. 启用hstore:

  1. => create extension hstore;  
  2. => \q   

3. 建立应用程序(这部依赖Maven的安装):

  1. $ mvn package 

4. 设置DATABASE_URL环境变量指向你的PostgreSQL服务器:

  1. $ export DATABASE_URL=postgres://username:password@localhost/databasename 

5. 运行应用程序:

  1. $ java -cp target/classes:target/dependency/* com.jamesward.Webapp 

6. 尝试一下

完美?!现在再试一下通过Heroku在云上运行。你需要完成以下几个步骤:

1. 安装Hero Toolbelt

2. 登陆Heroku:

  1. $ heroku login 

3. 建立一个新的应用程序:

  1. $ heroku create 

4. 添加Heroku Postgres:

  1. $ heroku addons:add heroku-postgresql:dev 

5. 通知Heroku完成基于刚添加数据库上的DATABASE_USL设置(手动重置YOUR_HEROKU_POSTGESQL_COLOR_URL):

  1. $ heroku pg:promote YOUR_HEROKU_POSTGRESQL_COLOR_URL 

6. 打开到数据库的psql连接:

  1. $ heroku pg:psql 

7. 让hstore完成对你数据库的支持:

  1. => create extension hstore;  
  2. => \q   

8. 部署应用程序:

  1. $ git push heroku master  

9. 在云端查看应用程序:

  1. $ heroku open   

在这里我们完成了使用postgresql、hibernate、spring、java在SQL数据库中实现NoSQL的全部演示,而在集思广益下NoSQL与SQL的融合也必将更加完美!(编译/仲浩 包研/责编 原文来自James Ward

posted on 2013-05-06 21:48  海山  阅读(640)  评论(0编辑  收藏  举报