前言:
最近在忙的一個(gè)項目是建立在Liferay Enterprise Portal上的,設計的幾張數據表要與已有的Portal數據庫中的User_表有級聯(lián)關(guān)系。之前從Liferay的官方網(wǎng)站上了解到Liferay的Portal持久化都是通過(guò)Hibernate來(lái)實(shí)現,故對其實(shí)現的方法產(chǎn)生了小小的興趣(因為我的數據表也打算通過(guò)Hibernate的O/R映射來(lái)實(shí)現,代碼中難免要使用Portal的類(lèi)com.liferay.portal.model.User)。
正文:
其實(shí)了解各種實(shí)現的方法,最好的莫過(guò)于讀源碼。(只要你有這個(gè)耐心)
我開(kāi)始只想通過(guò)userId得到User對象,關(guān)于User對象的各種相關(guān)的類(lèi)都在包com.liferay.portal.ejb里,你可以看到User開(kāi)頭的類(lèi)有一堆,呵呵,其實(shí)我們這里只要涉及幾個(gè)重要的類(lèi):
UserHBM.java 這個(gè)是User類(lèi)的一個(gè)翻版,里面的信息和User里的信息基本一致(沒(méi)仔細看),Portal也是通過(guò)這個(gè)類(lèi)來(lái)映射數據庫的User_表的。
UserPool.java 這個(gè)是一個(gè)與Cache相關(guān)的類(lèi),可不關(guān)心,并不影響理解。
UserManager.java 定義了與User相關(guān)的一組接口,對一些重要屬性如Group,Role等的添加刪除等。
UserManagerImpl.java 實(shí)現了UserManager接口,并繼承了PrincipalBean.java。
UserUtil.java 個(gè)人覺(jué)得有點(diǎn)象實(shí)體bean的變體,里面有create,remove,update等方法,還有一些查找方法。
UserPersistence.java 這個(gè)里面是具體數據庫的實(shí)現方法,UserUtil都是調用這個(gè)類(lèi)的方法。
讓我們先看看UserManagerImpl.java中關(guān)于得到User的代碼,源碼第400行
public User getUserById(String userId)
throws PortalException, SystemException {
userId = userId.trim().toLowerCase();
User user = UserUtil.findByPrimaryKey(userId);
if (getUserId().equals(userId) ||
hasAdministrator(user.getCompanyId())) {
return user;
}
else {
return (User)user.getProtected();
}
}
然后再看UserUtil.java的749行
protected static com.liferay.portal.model.User findByPrimaryKey(
java.lang.String userId)
throws com.liferay.portal.NoSuchUserException,
com.liferay.portal.SystemException {
UserPersistence persistence = (UserPersistence)InstancePool.get(PERSISTENCE);
return persistence.findByPrimaryKey(userId);
}
再找UserPersistence.java的3026行
protected com.liferay.portal.model.User findByPrimaryKey(String userId)
throws NoSuchUserException, SystemException {
com.liferay.portal.model.User user = UserPool.get(userId);
Session session = null;
try {
if (user == null) {
session = openSession();
UserHBM userHBM = (UserHBM)session.load(UserHBM.class, userId);
user = UserHBMUtil.model(userHBM);
}
return user;
}
catch (HibernateException he) {
if (he instanceof ObjectNotFoundException) {
throw new NoSuchUserException(userId.toString());
}
else {
throw new SystemException(he);
}
}
finally {
HibernateUtil.closeSession(session);
}
}
看完上面這些代碼是不是就明白Portal是怎么通過(guò)userId得到User對象的?上面一段代碼中紅色的那句用過(guò)hibernate的人都會(huì )很熟悉,通過(guò)主鍵得到對象。
我們再深入一下,看一下BasePersistence.java,這個(gè)是UserPersistence.java的父類(lèi),上面代碼中openSession()在這個(gè)類(lèi)里定義。
public class BasePersistence {
protected Session openSession() throws HibernateException {
return HibernateUtil.openSession(getHibernateConfigurationClassName());
}
protected Dialect getDialect() {
return HibernateUtil.getDialect(getHibernateConfigurationClassName());
}
protected String getHibernateConfigurationClassName() {
return HibernateConfiguration.class.getName();
}
}
再看com.liferay.portal.util.HibernateUtil.java的63行
public static Session openSession(String className)
throws HibernateException {
SessionConfiguration config =
_getSessionConfigurationInstance(className);
return config.openSession();
}
com.liferay.util.dao.hibernate.SessionConfiguration.java是一個(gè)抽象類(lèi),讓我直接看其子類(lèi)com.liferay.portal.util.HibernateConfiguration.java
public class HibernateConfiguration extends SessionConfiguration {
public void init() {
try {
ClassLoader classLoader = getClass().getClassLoader();
Configuration cfg = new Configuration();
String[] configs = StringUtil.split(
SystemProperties.get("hibernate.configs"));
for (int i = 0; i < configs.length; i++) {
try {
InputStream is =
classLoader.getResourceAsStream(configs[i]);
if (is != null) {
cfg = cfg.addInputStream(is);
is.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
cfg.setProperties(SystemProperties.getProperties());
setSessionFactory(cfg.buildSessionFactory());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
上面代碼中的紅色部分是從系統的properties文件中讀取一些值,實(shí)際上是調用portal-ejb/system.properties文件,從這個(gè)文件的第94行就可以發(fā)現一些Hibernate用來(lái)做O/R mapping的文件。代碼中通過(guò)InputStream方式把這些mapping files加到Configuration中去。
大家可以去看一下這些mapping files是不是我們所熟悉的****.hbm.xml的格式?
后記:
讀了一早上的源碼,寫(xiě)了一個(gè)小時(shí)的blog,無(wú)非是想切實(shí)的解決一個(gè)問(wèn)題。通過(guò)讀源碼可以了解一些機制,也可以了解一些設計思想,對于每一個(gè)學(xué)習者都是有益的。從開(kāi)始不知道用什么方法好,就去找admin portlet里找JSP(list-users.jsp),里面有一些相關(guān)的用戶(hù)管理的方法(User[] users = (User[])CompanyLocalManagerUtil.getUsers(company.getCompanyId()).toArray(new User[0]);),從中找到一個(gè)得到所有User的方法,也讓我聯(lián)想的去找一些相關(guān)的類(lèi),后來(lái)我就找到UserManagerUtil.java。這個(gè)過(guò)程是猜測到證實(shí)的過(guò)程,當你的猜測得到證實(shí)的時(shí)候,當你發(fā)現那個(gè)經(jīng)過(guò)多層包裝的你熟悉的接口方法的時(shí)候,那種感覺(jué)是快樂(lè )的,滿(mǎn)足的。
聯(lián)系客服