`
codecook
  • 浏览: 41966 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

封装Hibernate成Bundle

阅读更多
为什么要封装?
1,目前Hibernate没有提供Hibernate Bundle,只能自己封装.
2,封装第3方jar包是开发osgi程序的必备技能.

扩展模式(extender pattern):
介绍在此:http://felix.apache.org/site/extender-pattern-handler.html
不要被它高深的名字吓倒,简单地说就是一个Bundle负责监听,查看其他Bundle是否符合某种特征,如果符合,则对该bundle怎么怎么样;如果不符合,又对bundle怎么怎么样.
我们把hibernate.cfg.xml文件放在felix根目录下的cfg目录,把实体的映射文件放在各自实体bundle的mappingresource目录下.1个bundle负责监听其它bundle的安装和卸载,当bundle安装时,查看它的MANIFEST.MF中是否有HibernateEntity-Class属性,如果有,则载入mappingresource目录下的映射文件.

构建工具maven
  请使用maven吧!不要因为ant已经很强大而抗拒它. Felix提供了maven-bundle-plugin 这个  Bundle来构建其它bundle.它内部是使用了具有osgi瑞士军刀之称的bnd.

Action:
我们决定分装3个Bundle:
  1,Hibernate Lib Bundle.里面封装了Hibernate类库.
  2,Hibernate Service Bundle.该Bundle提供获得Session服务.
  3,Hibernate EntityRegister Bundle.该Bundle负责监听其他Bundle,使用了扩展模式.

封装Hibernate Lib Bundle
  把所有Hibernate相关的jar包统统放进去吧(明显不合理,但简单可行).Export一些别人需要使用的包吧.
 
封装ibernate Service Bundle
  只需提供一个接口即可.


public interface HibernateService {

	/**
	 * 获得Hibernate Session
	 * @return
	 */
	public Session getSession();
}


封装Hibernate EntityRegister Bundle
   监听其它Bundle的安装,载入符合条件的Bundle的hibernate映射文件,注册HibernateService服务实体.

/**
 * 常量
 *
 */
public class HibernateConstants {
	
	/**
	 * 包含Hibernate实体的Bundle属性标签
	 */
	public static final String HibernateBundleTag = "HibernateEntity-Class";
	/**
	 * Bundle内包含Hibernate映射文件的默认目录
	 */
	public static final String DefaultHibernateMappingDir = "mappingresource";
}


public class HibernateServiceImpl implements HibernateService {
	private String CONFIG_FILE_LOCATION = System.getProperty("user.dir")
			+ "/cfg/hibernate.cfg.xml";

	private Configuration configuration;

	private SessionFactory sessionFactory;

	private final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
	
	public Session getSession() {
		Session session = threadLocal.get();
		if (null == session || !session.isOpen()) {
			session = sessionFactory != null
					? sessionFactory.openSession()
					: null;
			threadLocal.set(session);
		}
		return session;
	}

	public HibernateServiceImpl() {

	}

	public List<String> listMappingFiles(String location) {
		List<String> result = new ArrayList<String>();
		if (location.endsWith(".jar")) {
			JarFile jar;
			try {
				// 获取jar
				jar = new JarFile(location);
				// 从此jar包 得到一个枚举类
				Enumeration<JarEntry> entries = jar.entries();
				// 同样的进行循环迭代
				while (entries.hasMoreElements()) {
					// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
					JarEntry entry = entries.nextElement();
					String name = entry.getName();
					// 如果是以/开头的
					if (name.charAt(0) == '/') {
						// 获取后面的字符串
						name = name.substring(1);
					}

					// 如果前半部分和定义的包名相同
					if (!entry.isDirectory()
							&& name.startsWith(HibernateConstants.DefaultHibernateMappingDir)) {
						result.add(name);
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	public boolean init(Bundle bundle) {
		try {
			//载入Hibernate.cfg.xml文件
			loadHibernateCfg();
			//是否是HibernateEntityBundle
			if (isHibernateEntityBundle(bundle)) {
				//设置当前线程的ClassLoader为Bundle的ClassLoader
				setBundleClassLoaderToCurrentThread(bundle);
				// 遍历bundle内的映射文件,添加到configuration中
				loadHibernateMappingFiles(bundle);
			}
			sessionFactory = configuration.buildSessionFactory();
		} catch (HibernateException e) {
			System.out.println("sessionFactory建立错误" + e);
			return false;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 是否是HibernateEntityBundle
	 * @param bundle
	 * @return
	 */
	private boolean isHibernateEntityBundle(Bundle bundle) {
		return bundle.getHeaders().get(HibernateConstants.HibernateBundleTag) != null;
	}

	/**
	 *  遍历bundle内的映射文件,添加到configuration中
	 * @param bundle
	 * @throws UnsupportedEncodingException
	 */
	private void loadHibernateMappingFiles(Bundle bundle)
			throws UnsupportedEncodingException {
		String urlLocation = bundle.getLocation();
		urlLocation = java.net.URLDecoder.decode(urlLocation, "utf-8");
		String jarLocation = urlLocation.substring(6);
		List<String> mappingFilePathList = listMappingFiles(jarLocation);

		for (String filePath : mappingFilePathList) {
			InputStream is = Thread.currentThread()
					.getContextClassLoader()
					.getResourceAsStream(filePath);
			configuration.addInputStream(is);
		}
	}

	/**
	 * 设置当前线程的ClassLoader为Bundle的ClassLoader
	 * @param bundle
	 * @throws ClassNotFoundException
	 */
	private void setBundleClassLoaderToCurrentThread(Bundle bundle)
			throws ClassNotFoundException {
		System.out.println("this bundle contains hibernate entity");
		String[] clazzs = bundle.getHeaders()
				.get(HibernateConstants.HibernateBundleTag).toString()
				.split(",");
		if (clazzs != null && clazzs.length > 0) {
			ClassLoader bundleClassLoader = bundle.loadClass(clazzs[0])
					.getClassLoader();
			Thread.currentThread().setContextClassLoader(
					bundleClassLoader);
		}
	}

	/**
	 * 载入Hibernate.cfg.xml文件
	 */
	private void loadHibernateCfg() {
		File file = new File(CONFIG_FILE_LOCATION);
		configuration = new Configuration();
		configuration.configure(file);
	}
}







分享到:
评论
3 楼 icecream0 2012-05-08  
我一直在纠结hibernate如何以扩展点的方式运行在felix中,但是一直找不到这种机制!楼主辛苦了,这篇文章让我茅塞顿开啊!只是对IPOJO了解很少,而且例子难找!不知可否发一份源码?感谢至极啊!icecream0211@gmail.com
2 楼 dengquanhao 2012-04-19  
楼主,这个是否可以提供bundle示例呢?不甚感激啊。邮箱:dengquanhao@163.com
1 楼 yusunnya 2012-03-21  
能把这3个bundle提供下载吗?  谢谢@!~~

相关推荐

Global site tag (gtag.js) - Google Analytics