眾所周知,關係資料類型一直是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伺服器技術,當然也可以通過Rails、Django及一些其他技術來實現。為了向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類:
- package com.jamesward.model;
-
- import net.backtothefront.HstoreUserType;
- import org.hibernate.annotations.Type;
- import org.hibernate.annotations.TypeDef;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import java.util.HashMap;
- import java.util.Map;
-
- @Entity
- @TypeDef(name = "hstore", typeClass = HstoreUserType.class)
- public class Contact {
-
- @Id
- @GeneratedValue
- public Integer id;
-
- @Column(nullable = false)
- public String name;
-
- @Type(type = "hstore")
- @Column(columnDefinition = "hstore")
- public Map<String, String> contactMethods = new HashMap<String, String>();
-
- }
如果你熟知Hibernate/JPA的話,那麼以上這些對於你來說都會非常的熟悉。而吸引你的陌生之處在於contactMethods對象的修飾 — Map<String, String>,並且還使用了PostgreSQL的hostore資料類型。為了正常運行,hostore資料的類型必須被定義以及columnDefinition集。這不得不再次感謝Jakub Gluszecki對HstoreHelper和HostoreUserTyper的整合,否則的話這一切都無法實現。
因為只是簡單的Hibernate/JPA,剩下的就比較簡單了。下面是做基本查詢和修改的ContactService類:
- package com.jamesward.service;
-
- import com.jamesward.model.Contact;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- import javax.persistence.EntityManager;
- import javax.persistence.PersistenceContext;
- import javax.persistence.criteria.CriteriaQuery;
-
- import java.util.List;
-
- @Service
- @Transactional
- public class ContactServiceImpl implements ContactService {
-
- @PersistenceContext
- EntityManager em;
-
- @Override
- public void addContact(Contact contact) {
- em.persist(contact);
- }
-
- @Override
- public List<Contact> getAllContacts() {
- CriteriaQuery<Contact> c = em.getCriteriaBuilder().createQuery(Contact.class);
- c.from(Contact.class);
- return em.createQuery(c).getResultList();
- }
-
- public Contact getContact(Integer id) {
- return em.find(Contact.class, id);
- }
-
- @Override
- public void addContactMethod(Integer contactId, String name, String value) {
- Contact contact = getContact(contactId);
- contact.contactMethods.put(name, value);
- }
-
- }
在你瞭解它的工作機制後,我們要開始嘗試在Heroku上面的示範了。
如果你想在本地或者Heroku上運行這個應用程式,那麼首先你必須提取原始碼然後繼續建立spring_hibernate_hstore_demo目錄的工作:
- $ git clone https://github.com/jamesward/spring_hibernate_hstore_demo.git
- $ cd spring_hibernate_hstore_demo
在本地運行需要做的工作:
1. 通過建立到pssql上的串連來允許PostgreSQL資料庫對hstore的支援:
- $ psql -U username -W -h localhost database
2. 啟用hstore:
- => create extension hstore;
- => \q
3. 建立應用程式(這部依賴Maven的安裝):
- $ mvn package
4. 設定DATABASE_URL環境變數指向你的PostgreSQL伺服器:
- $ export DATABASE_URL=postgres://username:password@localhost/databasename
5. 運行應用程式:
- $ java -cp target/classes:target/dependency/* com.jamesward.Webapp
6. 嘗試一下
完美?!現在再試一下通過Heroku在雲上運行。你需要完成以下幾個步驟:
1. 安裝Hero Toolbelt
2. 登陸Heroku:
- $ heroku login
3. 建立一個新的應用程式:
- $ heroku create
4. 添加Heroku Postgres:
- $ heroku addons:add heroku-postgresql:dev
5. 通知Heroku完成基於剛添加資料庫上的DATABASE_USL設定(手動重設YOUR_HEROKU_POSTGESQL_COLOR_URL):
- $ heroku pg:promote YOUR_HEROKU_POSTGRESQL_COLOR_URL
6. 開啟到資料庫的psql串連:
- $ heroku pg:psql
7. 讓hstore完成對你資料庫的支援:
- => create extension hstore;
- => \q
8. 部署應用程式:
- $ git push heroku master
9. 在雲端查看應用程式:
- $ heroku open
在這裡我們完成了使用postgresql、hibernate、spring、java在SQL資料庫中實現NoSQL的全部示範,而在集思廣益下NoSQL與SQL的融合也必將更加完美!(編譯/仲浩 包研/責編 原文來自James Ward)