成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Google App Engine的Java持久性與數(shù)據(jù)存儲

開發(fā) 開發(fā)工具
本文是Rick Hightower的Google App Engine介紹系列的第三部分,他將在這篇文章中講述有關(guān)持久層和關(guān)系中一些需要學(xué)習(xí)的知識。

本文繼續(xù)介紹Google App Engine for Java。這篇講述持久性和關(guān)系。

Google App Engine for Java 力求為可伸縮的 Web 應(yīng)用程序成功地編寫一個持久層,可這個目標(biāo)的達(dá)成情況又如何呢?在本文中,我將概述 App Engine for Java 的持久性框架,從而結(jié)束本系列文章。該框架以 Java Data Objects(JDO)和 Java Persistence API(JPA)為基礎(chǔ)。盡管在剛剛出現(xiàn)時前景良好,但是 App Engine 的基于 Java 的持久性目前存在一些嚴(yán)重的缺陷,我將對此進(jìn)行解釋和演示。您將學(xué)習(xí) App Engine for Java 持久性是如何運作以及有著哪些挑戰(zhàn),還將學(xué)習(xí)在使用面向 Java 開發(fā)人員的 Google 云平臺時,您具有哪些持久性選擇。

在閱讀本文并遍覽這些示例時,您要牢記這樣的事實:現(xiàn)在的 App Engine for Java 是一個預(yù)覽 版。基于 Java 的持久性目前也許并不是您所希望或者需要的全部,可能并且應(yīng)該會在未來發(fā)生變化。現(xiàn)如今,使用 App Engine for Java 進(jìn)行可伸縮的、數(shù)據(jù)密集型的 Java 應(yīng)用程序開發(fā)不合適膽小者或者保守派,這就是我在撰寫本文時所學(xué)到的。這更像跳入了游泳池的最深處:看不到任何救生員,項目要沉下去還是往前游,取決于您自己。

注意,本文中的示例應(yīng)用程序以 第 2 部分 中開發(fā)的聯(lián)系人管理應(yīng)用程序為基礎(chǔ)。您需要構(gòu)建該應(yīng)用程序,確保它是可運行的,這樣才能繼續(xù)學(xué)習(xí)本文的示例。

基礎(chǔ)知識和抽象泄漏(leaky abstraction)

與原始的 Google App Engine 一樣,App Engine for Java 依靠 Google 的內(nèi)部基礎(chǔ)設(shè)施,實現(xiàn)可伸縮的應(yīng)用程序開發(fā)的 Big Three:分布、復(fù)制和負(fù)載均衡。由于使用的是 Google 基礎(chǔ)設(shè)施,因此所有神奇的地方大都發(fā)生在后臺,可以通過 App Engine for Java 的基于標(biāo)準(zhǔn)的 API 獲得。數(shù)據(jù)存儲接口是以 JDO 和 JPA 為基礎(chǔ)的,而它們自身又是以開源的 DataNucleus 項目為基礎(chǔ)。AppEngine for Java 還提供了一個低級別的適配器 API,用來直接處理基于 Google 的 BigTable 實現(xiàn)的 App Engine for Java 數(shù)據(jù)存儲(要了解更多有關(guān) BigTable 的信息,請參見 第 1 部分)。

然而,App Engine for Java 數(shù)據(jù)持久性并不像純 Google App Engine 中的持久性那樣簡單。由于 BigTable 不是一個關(guān)系數(shù)據(jù)庫,JDO 和 JPA 的接口出現(xiàn)了一些抽象泄漏。例如,在 App Engine for Java 中,您無法進(jìn)行那些執(zhí)行連接的查詢。您可以在 JPA 和 JDO 間設(shè)置關(guān)系,但它們只能用來持久化關(guān)系。并且在持久化對象時,如果它們在相同的實體群中,那么它們只能被持久化到相同的原子事務(wù)中。根據(jù)慣例,具有所有權(quán)的關(guān)系位于與父類相同的實體群中。相反,不具有所有權(quán)的關(guān)系可以在不同的實體群中。

重新考慮數(shù)據(jù)規(guī)范化

要使用 App Engine 的可伸縮的數(shù)據(jù)存儲,需要重新考慮有關(guān)規(guī)范化數(shù)據(jù)的優(yōu)點的教導(dǎo)。當(dāng)然,如果您在真實的環(huán)境中工作了足夠長的時間,那么,您可能已經(jīng)為了追求性能而犧牲過規(guī)范化了。區(qū)別在于,在處理 App Engine 數(shù)據(jù)存儲時,您必須盡早且經(jīng)常進(jìn)行反規(guī)范化。反規(guī)范化 不再是一個忌諱的字眼,相反,它是一個設(shè)計工具,您可以把它應(yīng)用在 App Engine for Java 應(yīng)用程序的許多方面。

當(dāng)您嘗試把為 RDBMS 編寫的應(yīng)用程序移植到 App Engine for Java 時,App Engine for Java 的持久性泄漏的主要缺陷就會顯露出來。App Engine for Java 數(shù)據(jù)存儲并不是關(guān)系數(shù)據(jù)庫的臨時替代物,因此,要把您對 App Engine for Java 所做的工作移植到 RDBMS 端口并不容易。采用現(xiàn)有的模式并把它移植到數(shù)據(jù)存儲中,這種場景則更為少見。如果您決定把一個遺留的 Java 企業(yè)應(yīng)用程序移植到 App 引擎中,建議您要小心謹(jǐn)慎,并進(jìn)行備份分析。Google App Engine 是一個針對專門為它設(shè)計的應(yīng)用程序的平臺。Google App Engine for Java 支持 JDO 和 JPA,這使得這些應(yīng)用程序能夠被移植回更傳統(tǒng)的、未進(jìn)行規(guī)范化的企業(yè)應(yīng)用程序。

關(guān)系的問題

App Engine for Java 目前的預(yù)覽版的另外一個缺點是它對關(guān)系的處理。為了創(chuàng)建關(guān)系,現(xiàn)在您必須對 JDO 使用 App Engine for Java 特有的擴(kuò)展。假設(shè)鍵是在 BigTable 的工件的基礎(chǔ)上生成 — 也就是說,“主鍵” 將父對象鍵編碼到其所有子鍵中 — 您將不得不在一個非關(guān)系數(shù)據(jù)庫中管理數(shù)據(jù)。另外一個限制是持久化數(shù)據(jù)。如果您使用非標(biāo)準(zhǔn)的 AppEngine for Java Key 類,事情將會變得復(fù)雜。首先,把模型移植到 RDBMS 時,如何使用非標(biāo)準(zhǔn) Key? 其次,由于無法使用 GWT 引擎轉(zhuǎn)換 Key 類,因此,任何使用這個類的模型對象都無法被作為 GWT 應(yīng)用程序的一部分進(jìn)行使用。

當(dāng)然,撰寫這篇文章時,Google App Engine for Java 還是純粹的預(yù)覽模式,沒有到發(fā)布的最佳時間。學(xué)習(xí) JDO 中的關(guān)系文檔(很少,而且包含一些不完整的示例)時,這點就變得顯而易見了。

App Engine for Java 開發(fā)包提供了一系列的示例程序。許多示例都使用 JDO,沒有一個使用 JPA。這些示例中沒有一個示例(包括一個名為 jdoexamples 的示例)演示了關(guān)系,即使是簡單的關(guān)系。相反,所有的示例都只使用一個對象把數(shù)據(jù)保存到數(shù)據(jù)存儲中。Google App Engine for Java 討論組 充斥著有關(guān)如何使簡單關(guān)系起作用的問題,但卻鮮有答案。很顯然,有些開發(fā)人員有辦法使其起作用,但是實現(xiàn)起來都很困難,而且遇到了一些復(fù)雜情況。

App Engine for Java 中的關(guān)系的底線是,無需從 JDO 或 JPA 獲得大量支持就能夠管理它們。 Google 的 BigTable 是一種已經(jīng)經(jīng)過檢驗的技術(shù),可用來生成可伸縮的應(yīng)用程序,然而,您還可以在此基礎(chǔ)上進(jìn)行構(gòu)建。在 BigTable 上進(jìn)行構(gòu)建,您就不必處理還不完善的 API 層面。另一方面,您只要處理一個較低級別的 API。

#p#

App Engine for Java 中的 Java Data Objects

把傳統(tǒng)的 Java 應(yīng)用程序移植到 App Engine for Java 中,甚至是給出關(guān)系挑戰(zhàn),這些可能都沒有什么意義,然而,持久性場景還是存在的,這時使用這個平臺就有意義了。我將使用一個可行的示例來結(jié)束本文,您將體驗 App Engine for Java 持久性是如何工作的。我們將以 第 2 部分 中建立的聯(lián)系人管理應(yīng)用程序為基礎(chǔ),介紹如何添加支持,以使用 App Engine for Java 數(shù)據(jù)存儲工具持久化 Contact 對象。

在前面的文章中,您創(chuàng)建了一個簡單的 GWT GUI,對 Contact 對象進(jìn)行 CRUD 操作。您定義了簡單的接口,如清單 1 所示:

清單 1. 簡單的 ContactDAO 接口
				
package gaej.example.contact.server;

import java.util.List;

import gaej.example.contact.client.Contact;

public interface ContactDAO {
	void addContact(Contact contact);
	void removeContact(Contact contact);
	void updateContact(Contact contact);
	List<Contact> listContacts();
}

接下來,創(chuàng)建一個模擬版本,與內(nèi)存集合中的數(shù)據(jù)進(jìn)行交互,如清單 2 所示:

清單 2. 模擬 DAO 的 ContactDAOMock
				
package gaej.example.contact.server;

import gaej.example.contact.client.Contact;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ContactDAOMock implements ContactDAO {

	Map<String, Contact> map = new LinkedHashMap<String, Contact>();
	
	{
		map.put("rhightower@mammatus.com", new Contact("Rick Hightower", 
                                 "rhightower@mammatus.com", "520-555-1212"));
		map.put("scott@mammatus.com", new Contact("Scott Fauerbach", 
                                 "scott@mammatus.com", "520-555-1213"));
		map.put("bob@mammatus.com", new Contact("Bob Dean", 
                                 "bob@mammatus.com", "520-555-1214"));

	}
	
	public void addContact(Contact contact) {
		String email = contact.getEmail();
		map.put(email, contact);
	}

	public List<Contact> listContacts() {
		return Collections.unmodifiableList(new ArrayList<Contact>(map.values()));
	}

	public void removeContact(Contact contact) {
		map.remove(contact.getEmail());
	}

	public void updateContact(Contact contact) {		
		map.put(contact.getEmail(), contact);
	}

}

現(xiàn)在,使用與 Google App Engine 數(shù)據(jù)存儲交互的應(yīng)用程序替換模擬實現(xiàn),看看會發(fā)生什么。在這個示例中,您將使用 JDO 持久化 Contact 類。使用 Google Eclipse Plugin 編寫的應(yīng)用程序已經(jīng)擁有了使用 JDO 所需的所有庫。它還包含了一個 jdoconfig.xml 文件,因此,一旦對 Contact 類進(jìn)行了注釋,您就已經(jīng)準(zhǔn)備好開始使用 JDO。

清單 3 顯示擴(kuò)展后的 ContactDAO 接口,可使用 JDO API 進(jìn)行持久化、查詢、更新和刪除對象:

清單 3. 使用 JDO 的 ContactDAO
				
package gaej.example.contact.server;

import gaej.example.contact.client.Contact;

import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

public class ContactJdoDAO implements ContactDAO {
	private static final PersistenceManagerFactory pmfInstance = JDOHelper
			.getPersistenceManagerFactory("transactions-optional");

	public static PersistenceManagerFactory getPersistenceManagerFactory() {
		return pmfInstance;
	}

	public void addContact(Contact contact) {
		PersistenceManager pm = getPersistenceManagerFactory()
				.getPersistenceManager();
		try {
			pm.makePersistent(contact);
		} finally {
			pm.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Contact> listContacts() {
		PersistenceManager pm = getPersistenceManagerFactory()
				.getPersistenceManager();
		String query = "select from " + Contact.class.getName();
		return (List<Contact>) pm.newQuery(query).execute();
	}

	public void removeContact(Contact contact) {
		PersistenceManager pm = getPersistenceManagerFactory()
				.getPersistenceManager();
		try {
			pm.currentTransaction().begin();

			// We don't have a reference to the selected Product.
			// So we have to look it up first,
			contact = pm.getObjectById(Contact.class, contact.getId());
			pm.deletePersistent(contact);

			pm.currentTransaction().commit();
		} catch (Exception ex) {
			pm.currentTransaction().rollback();
			throw new RuntimeException(ex);
		} finally {
			pm.close();
		}
	}

	public void updateContact(Contact contact) {
		PersistenceManager pm = getPersistenceManagerFactory()
				.getPersistenceManager();
		String name = contact.getName();
		String phone = contact.getPhone();
		String email = contact.getEmail();

		try {
			pm.currentTransaction().begin();
			// We don't have a reference to the selected Product.
			// So we have to look it up first,
			contact = pm.getObjectById(Contact.class, contact.getId());
			contact.setName(name);
			contact.setPhone(phone);
			contact.setEmail(email);
			pm.makePersistent(contact);
			pm.currentTransaction().commit();
		} catch (Exception ex) {
			pm.currentTransaction().rollback();
			throw new RuntimeException(ex);
		} finally {
			pm.close();
		}
	}

}

#p#

逐一比對方法

現(xiàn)在,考慮一下使用清單 3 中的每個方法時發(fā)生的情況。您將會發(fā)現(xiàn),方法的名字可能是新的,但它們的動作大部分情況下都應(yīng)該感到熟悉。

首先,為了獲取 PersistenceManager,創(chuàng)建了一個靜態(tài)的 PersistenceManagerFactory。如果您以前使用過 JPA,PersistenceManager 與 JPA 中的 EntityManager 很相似。如果您使用過 Hibernate,PersistenceManager 與 Hibernate Session 很相似。基本上,PersistenceManager 是 JDO 持久性系統(tǒng)的主接口。它代表了與數(shù)據(jù)庫的會話。getPersistenceManagerFactory() 方法返回靜態(tài)初始化的 PersistenceManagerFactory,如清單 4 所示:

清單 4. getPersistenceManagerFactory() 返回 PersistenceManagerFactory
				
private static final PersistenceManagerFactory pmfInstance = JDOHelper
		.getPersistenceManagerFactory("transactions-optional");

public static PersistenceManagerFactory getPersistenceManagerFactory() {
	return pmfInstance;
}

addContact() 方法把新的聯(lián)系人添加到數(shù)據(jù)存儲中。為了做到這點,需要創(chuàng)建一個 PersistenceManager 實例,然后,調(diào)用 PersistenceManagermakePersistence() 方法。makePersistence() 方法采用臨時的 Contact 對象(用戶將在 GWT GUI 中填充),并且使其成為一個持久的對象。所有這些如清單 5 所示:


清單 5. addContact()
				
public void addContact(Contact contact) {
	PersistenceManager pm = getPersistenceManagerFactory()
			.getPersistenceManager();
	try {
		pm.makePersistent(contact);
	} finally {
		pm.close();
	}
}

注意在清單 5 中,persistenceManager 是如何被封入在 finally 塊中。這確保能夠把與 persistenceManager 關(guān)聯(lián)的資源清除干凈。

如清單 6 所示,listContact() 方法從它所查找的 persistenceManager 中創(chuàng)建一個查詢對象。它調(diào)用了 execute() 方法,從數(shù)據(jù)存儲中返回 Contact 列表。


清單 6. listContact()
				
@SuppressWarnings("unchecked")
public List<Contact> listContacts() {
	PersistenceManager pm = getPersistenceManagerFactory()
			.getPersistenceManager();
	String query = "select from " + Contact.class.getName();
	return (List<Contact>) pm.newQuery(query).execute();
}

在從數(shù)據(jù)存儲中刪除聯(lián)系人之前,removeContact() 通過 ID 查找聯(lián)系人,如清單 7 所示。它必須這么做,而不僅僅是把聯(lián)系人直接刪除,這是因為來自 GWT GUI 的 Contact 對 JDO 一無所知。在刪除前,您必須獲得與 PersistenceManager 緩存關(guān)聯(lián)的 Contact


清單 7. removeContact()
				
public void removeContact(Contact contact) {
	PersistenceManager pm = getPersistenceManagerFactory()
			.getPersistenceManager();
	try {
		pm.currentTransaction().begin();

		// We don't have a reference to the selected Product.
		// So we have to look it up first,
		contact = pm.getObjectById(Contact.class, contact.getId());
		pm.deletePersistent(contact);

		pm.currentTransaction().commit();
	} catch (Exception ex) {
		pm.currentTransaction().rollback();
		throw new RuntimeException(ex);
	} finally {
		pm.close();
	}
}

清單 8 中的 updateContact() 方法與 removeContact() 方法類似,用來查找 Contact。然后,updateContact() 方法從 Contact 中復(fù)制屬性。這些屬性被當(dāng)作實參(Argument)傳送到 Contact,后者由持久性管理器查找。使用 PersistenceManager 檢查所查找的對象發(fā)生的變化。如果對象發(fā)生了變化,當(dāng)事務(wù)進(jìn)行提交時,這些變化會被 PersistenceManager 刷新到數(shù)據(jù)庫。


清單 8. updateContact()
				
public void updateContact(Contact contact) {
	PersistenceManager pm = getPersistenceManagerFactory()
			.getPersistenceManager();
	String name = contact.getName();
	String phone = contact.getPhone();
	String email = contact.getEmail();

	try {
		pm.currentTransaction().begin();
		// We don't have a reference to the selected Product.
		// So we have to look it up first,
		contact = pm.getObjectById(Contact.class, contact.getId());
		contact.setName(name);
		contact.setPhone(phone);
		contact.setEmail(email);
		pm.makePersistent(contact);
		pm.currentTransaction().commit();
	} catch (Exception ex) {
		pm.currentTransaction().rollback();
		throw new RuntimeException(ex);
	} finally {
		pm.close();
	}
}

#p#

對象持久性注釋

為了使 Contact 能夠具有持久性,必須把它識別為一個具有 @PersistenceCapable 注釋的可持久性對象。然后,需要對它所有的可持久性字段進(jìn)行注釋,如清單 9 所示:


清單 9. Contact 具有可持久性
				
package gaej.example.contact.client;

import java.io.Serializable;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Contact implements Serializable {

	private static final long serialVersionUID = 1L;
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long id;
	@Persistent
	private String name;
	@Persistent
	private String email;
	@Persistent
	private String phone;

	public Contact() {

	}

	public Contact(String name, String email, String phone) {
		super();
		this.name = name;
		this.email = email;
		this.phone = phone;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

}

通過面向?qū)ο蟮木幊毯徒涌谠O(shè)計原則,您只需使用新的 ContactJdoDAO 替代原始的 ContactDAOMock。然后 GWT GUI 無需任何修改就可處理 JDO。

最后,在這種替換中,真正改變 的是 DAO 在服務(wù)中被實例化的方式。如清單 10 所示:


清單 10. RemoteServiceServlet
				
public class ContactServiceImpl extends RemoteServiceServlet implements ContactService {
	private static final long serialVersionUID = 1L;
	//private ContactDAO contactDAO = new ContactDAOMock();
	private ContactDAO contactDAO = new ContactJdoDAO();
...

結(jié)束語

在這篇由三部分組成的文章中,介紹了 Google App Engine for Java 目前為持久性提供的支持,這是交付可伸縮應(yīng)用程序的基礎(chǔ)。總的結(jié)論令人失望,但是要注意這是一個正在發(fā)展中的平臺。為 App Engine for Java 預(yù)覽版編寫的應(yīng)用程序被連接到 App Engine 的持久性基礎(chǔ)設(shè)施,即使是用 JDO 或 JPA 編寫。App Engine for Java 預(yù)覽版幾乎沒有為它的持久性框架提供任何文檔,而且 App Engine for Java 提供的示例幾乎無法演示即使是最簡單的關(guān)系。

即使 JDO 和 JPA 實現(xiàn)已經(jīng)完全成熟,目前您仍然不可能編寫一個 App Engine for Java 應(yīng)用程序并輕松地把它移植到一個基于 RDBMS 的企業(yè)應(yīng)用程序。要使移植能夠起作用,至少要編寫大量的代碼。

我希望持久性能隨著時間的推移而成熟起來。如果現(xiàn)在必須使用 App Engine for Java,您可能需要繞過 Java API,直接編寫低級別的 Datastore API。使用 App Engine for Java 平臺是可能的,但是,如果習(xí)慣了使用 JPA 和/或 JDO,那么將出現(xiàn)一條學(xué)習(xí)曲線,因為存在本文前面描述的抽象泄漏,并且目前的功能要么還無法正常運行,要么還沒有進(jìn)行很好的文檔記錄。

責(zé)任編輯:yangsai 來源: IBMDW
相關(guān)推薦

2013-07-09 10:18:58

VDI虛擬化

2022-10-27 08:00:32

DockerAWS云容器

2021-05-25 10:20:31

Python持久性編程語言

2023-12-08 08:26:05

數(shù)據(jù)存儲持久性

2019-09-06 09:50:52

云存儲硬盤云服務(wù)

2009-09-27 09:55:38

Hibernate持久

2009-09-02 11:34:09

Google App

2021-01-22 10:40:08

Linux文件內(nèi)存

2009-09-23 15:25:08

Hibernate 3

2009-06-26 16:32:22

App Engine文檔存儲文檔搜索

2009-04-13 15:48:54

Google AppJavaSun

2009-04-08 16:47:11

GoogleApp EngineJava

2009-04-09 08:54:07

App EnginegoogleJava

2009-04-09 09:53:43

GoogleAppEngineJava

2009-09-10 10:11:44

Google App Java開發(fā)2.0

2012-08-01 14:12:45

IBMdW

2014-06-05 14:41:05

亞馬遜AWS

2021-06-02 08:00:00

MOSH開源工具

2009-07-14 09:25:43

Google App GAEJava SDK 1.

2013-07-30 12:29:19

Google App Google技術(shù)Engine
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久精品免费 | 91亚洲一区| 日韩成人免费 | 日韩欧美理论片 | 91免费在线 | 91精品久久久久久久久久 | 亚洲精品日本 | 国产亚洲一区二区三区在线 | 久久久久久蜜桃一区二区 | 天堂国产 | 国产精品久久久久久久久久久免费看 | 欧美日韩在线观看一区二区三区 | h片在线看| 四虎国产| 插插插干干干 | 亚洲最新在线视频 | 在线看国产 | 最新中文字幕一区 | 福利国产| 国产成人精品a视频一区www | 久久久xx | 在线一区视频 | 亚洲免费在线 | 91麻豆精品国产91久久久久久 | 久久久精品一区二区三区 | 久久久久久国产精品免费免费狐狸 | 一区二区三区福利视频 | 久久美国 | 国产在线视频一区 | 久久一久久 | 日本久久精品视频 | 黄视频免费 | 国产精品区二区三区日本 | 亚洲性爰 | 一区二区三区免费在线观看 | 精品久久久久久亚洲国产800 | 免费国产精品久久久久久 | 老司机成人在线 | 国产小视频在线观看 | 一级a性色生活片久久毛片 一级特黄a大片 | www操操|