Kodo定義了什么模式呢?
mysql> use kododb;
mysql> show create table message;
| message | CREATE TABLE `message` (
`id` bigint(20) NOT NULL,
`body` varchar(255) default NULL,
`createdOn` datetime default NULL,
PRIMARY KEY (`id`)
)
注意,Kodo沒有像 Hibernate那樣標記auto-increment的id 。Kodo由自己指派自動生成的標識符。
這個bug是怎么回事?
到目前為止,一切似乎都運行良好。我們安裝了Hibernate,然后使用Hibernate運行了一個應用程序。然來又將提供者切換為Kodo。您可以用OpenJPA進行類似的測試(它的提供者是org.apache.openjpa.persistence.PersistenceProviderImpl。但是,由于在Weblogic Server中這個提供者是默認的,所以您甚至可以省略它)。那么切換提供者產生的bug在哪兒呢?
如果您決定以不同的方式安裝Hibernate,那么就會出現bug。如果不把Hibernate庫放在域的共享庫中,Hibernate庫還可以放在EAR里。如果這樣進行部署封裝,則應用程序就不能再次進行部署和撤除(即便將同樣的Hibernate作為提供者)。這是為什么呢?
答案就在于JPA自身提供的一個javax.persistence.Persistence類。這個類用于引導。它搜索可用的提供者并要求每個提供者創建一個持久性單元,即EntityManagerFactory。然而,這個引導類javax.persistence.Persistence會將PersistenceProvider類緩存在一個內部靜態Set中,并且不再對Set成員進行更新。
因此,如果用Web應用程序W封裝了Hibernate,一旦用戶應用程序直接調用或者由注入過程調用Persistence.createEntityManagerFactory(),則Hibernate持久性提供者X將被Web應用程序W的類裝載器 L1加載,并且緩存在javax.persistence.Persistence的靜態Set中。隨后,Web應用程序W被撤除。L1便會離開作用域。Web應用程序W將被重新部署。這時的類裝載器是L2。如果程序再次調用Persistence.createEntityManagerFactory(),則javax.persistence.Persistence中的代碼將試圖調用X的方法(由L1加載的,而L1已經不在了),而且代碼將開始與ClassCastException和長的堆棧跟蹤斷開。
如何解決這一bug呢?
一個簡單的解決方案是遵守這里所描述的封裝模式。還有一個有難度的方案是修改javax.persistence.Persistence本身。這個方案有難度是因為這一過程中要升級/修補/重新分配一個按照規范定義的(提供的)實現類。
在另一篇文章中,我將討論在如何對javax.persistence.Persistence類進行修改,從而允許在涉及多個(可能是不相干的)類裝載器的環境中更加良好地運行。
文章來源于領測軟件測試網 http://www.kjueaiud.com/