论坛首页 Java企业应用论坛

hibernate在新项目上应用的弊端

浏览 42037 次
该帖已经被评为隐藏帖
作者 正文
   发表时间:2011-04-29  
关于hql不能实现整个系统的要求,我们项目就有如下要求。
系统需要生成各种报表,包括销售、价格、库存、财务等待,这些报表都很复杂,我们的大部分SQL都超出了4000字符。
我们采用的方式是SQL同一管理,现在然后在代码中同一引用,这样方便管理,数据库有变化,则修改SQL和hibernate的配置文件即可。

关于同时管理hql和sql导致维护成本提高问题:
我还参加了另外一个老项目的修改,这个项目也是hibernate实现,但是也是有复杂SQL直接写在代码中,这时候数据库有变化了,我就得到代码中找相应的SQL修改,同时还有修改hibernate配置文件,当然这个和系统本身的SQL没统一管理有直接关系
0 请登录后投票
   发表时间:2011-04-29  
关于hibernate的效率问题,我对hibernate生成的SQL太长很不爽,而且一个插入语句经常要生生成两个SQL,一个是select一个是insert语句,也不爽。
另外用我只是要查询一个表的数据,往往会查询了多个其他相关的表,当然了如果设置成lazy=true就可解决,但是这时候我们设计代码就得多考虑一下这个表示不是要用lazy呢?这必然导致成本提高。

当然了,以上也是我个人hibernate水平不高导致,欢迎拍砖
0 请登录后投票
   发表时间:2011-04-29  
newslxw 写道
java_bigniu 写道
用了hibernate还老想着这表那表的,难怪了
真正的hibernate高手脑子中式没有表这个东西的
都是对象,考虑的是对象和对象之间的关系


我不赞同一对象方式设计数据库,目前主流数据库都是关系数据库,并不适合使用对象方式设计,个人影响,对象方式设计数据库的系统效率不高。
所以我使用hibernate时,还是先以关系方式设计数据库,根据需求、功能、模型设计数据库,然后再生成hibernate的pojo和xml

我们老大也是先设计表,再用hibernate,我感觉他本末倒置了

另:
xml在我们项目组是坚决禁止使用的
当有N个实体类的时候,配置文件太多了
我们都用annotation
0 请登录后投票
   发表时间:2011-04-29  
java_bigniu 写道
newslxw 写道
java_bigniu 写道
用了hibernate还老想着这表那表的,难怪了
真正的hibernate高手脑子中式没有表这个东西的
都是对象,考虑的是对象和对象之间的关系


我不赞同一对象方式设计数据库,目前主流数据库都是关系数据库,并不适合使用对象方式设计,个人影响,对象方式设计数据库的系统效率不高。
所以我使用hibernate时,还是先以关系方式设计数据库,根据需求、功能、模型设计数据库,然后再生成hibernate的pojo和xml

我们老大也是先设计表,再用hibernate,我感觉他本末倒置了

另:
xml在我们项目组是坚决禁止使用的
当有N个实体类的时候,配置文件太多了
我们都用annotation

是啊,xml多了很难管理,但是用annotation也出现同样的问题,甚至我还不知道那里用到了什么关系,对全局review和统计代码带来很多不便
0 请登录后投票
   发表时间:2011-04-29  
hibernate 我从来没有用过,我只用ibatis
0 请登录后投票
   发表时间:2011-04-29  
newslxw 写道

1、lazy加载,经常带来问题

我也遇到过
session开关不知道在哪儿比较妥当
0 请登录后投票
   发表时间:2011-05-13  
凡是盲目崇拜Hibernate的都是傻X,Hibernate本身也是傻X,又要求数据库结构设计怎样怎样,又要求类设计怎样怎样,什么都按你的设计来,你还不如直接生成应用程序算了!
0 请登录后投票
   发表时间:2011-05-14  
话说 好像没有什么框架是十全十美的!
0 请登录后投票
   发表时间:2011-07-05   最后修改:2012-03-01
assdust110 写道
nishijia 写道
弱弱地问一下,lazy加载的问题 该如何解决? 我曾经听过一个多年的架构师用hibernate,遇到lazy加载的时候session关闭的问题,最后只好关掉lazy

你那个问题应该是struts+hibernate集成的时候(或类似的框架集成),在控制器中关闭了hibernate的session,而后在页面中你又要迭代对象集合,结果对象集合中的A对象包含了B对象的实体在被访问的时候出现了session关闭的问题,不知是不是这样理解的?这个问题产生的根源其实你去想想程序执行的流程就可以了,用spring,用filter都可以解决这个问题。


用DTO生成器,您看能解决这个问题吗?

 

/**
 * 从PO到VO的转换,根据属性选择器,自动加载属性
 *
 * @param <X>
 * @param object
 * @param selector 属性选择器
 * @return
 */
@SuppressWarnings("unchecked")
public <X> X toVO(X object, Selector selector) {
	// 参数判断
	if (object == null)
		return null;
	X newObject = null;
	try {
		Class<X> destClass = HibernateProxyHelper
				.getClassWithoutInitializingProxy(object);
		//要求所有的PO都有一个无参的构造方法
		newObject = destClass.newInstance();
		ClassMetadata metadata = getSessionFactory().getClassMetadata(
				destClass);
		// 主键属性名
		String identityfier = metadata.getIdentifierPropertyName();
		// 复制主键
		ReflectionUtils.setProperty(newObject, identityfier,
				ReflectionUtils.getProperty(object, identityfier));
		// TODO 判断实体的加载模式,如果是即时加载,就跟属性一样直接加载
		// Object idVal = metadata.getPropertyValue(object, identityfier,
		// EntityMode.POJO);
		// metadata.setPropertyValue(newObject, identityfier, idVal,
		// EntityMode.POJO);
		// metadata.hasProxy();
		// boolean[] lazies = metadata.getPropertyLaziness();
		String[] properties = metadata.getPropertyNames();
		for (int i = 0; i < properties.length; i++) {
			String prop = properties[i];
			Type propType = metadata.getPropertyType(prop);

			// 简单属性,直接copy
			if (!propType.isEntityType() && !propType.isCollectionType()) {
				// 其他标量的属性,直接copy
				ReflectionUtils.setProperty(newObject, prop,
						ReflectionUtils.getProperty(object, prop));
				// metadata.setPropertyValue(newObject, prop,
				// metadata.getPropertyValue(object, prop, EntityMode.POJO),
				// EntityMode.POJO);
				continue;
			}
			// 复杂属性,先判断选择器是否为空,为空就直接跳过
			if (selector == null)
				continue;
			// 判断是否要加载此对象
			boolean needLoad = needLoad(propType, true, prop, selector);
			// 如果不要加载,直接跳过
			if (!needLoad)
				continue;
			// 取得属性值
			Object propVal = ReflectionUtils.getProperty(object, prop);
			// Object propVal = metadata.getPropertyValue(object, prop,
			// EntityMode.POJO);
			// 如果属性值为空,直接跳过
			if (propVal == null)
				continue;
			// 获取选择器的子选择器
			Selector subSelector = selector.generateSubSelector(prop);
			// 如果是实体类型,直接递归调用
			if (propType.isEntityType()) {
				ReflectionUtils.setProperty(newObject, prop, toVO(propVal,
						subSelector));
				// metadata.setPropertyValue(newObject, prop, propVal,
				// EntityMode.POJO);
				continue;
			}
			// 如果是集合属性,分各种情况处理
			if (propType.isCollectionType()) {
				// list型的属性
				if (propType instanceof ListType) {
					List listVal = (List) propVal;
					if (listVal.size() == 0)
						continue;
					List newVal = new ArrayList(listVal.size());
					for (Iterator it = listVal.iterator(); it.hasNext(); ) {
						newVal.add(toVO(it.next(), subSelector));
					}
					ReflectionUtils.setProperty(newObject, prop, newVal);
					// metadata.setPropertyValue(newObject, prop, newVal,
					// EntityMode.POJO);
					continue;
				}
				// Set型的属性
				if (propType instanceof SetType) {
					Set setVal = (Set) propVal;
					if (setVal.size() == 0)
						continue;
					Set newVal = new HashSet(setVal.size());
					for (Iterator it = setVal.iterator(); it.hasNext(); ) {
						newVal.add(toVO(it.next(), subSelector));
					}
					ReflectionUtils.setProperty(newObject, prop, newVal);
					// metadata.setPropertyValue(newObject, prop, newVal,
					// EntityMode.POJO);
					continue;
				}
				// Map型的属性
				if (propType instanceof MapType) {
					Map mapVal = (Map) propVal;
					if (mapVal.size() == 0)
						continue;
					Map newVal = new HashMap(mapVal.size());
					for (Iterator<Map.Entry> it = mapVal.entrySet().iterator(); it
							.hasNext(); ) {
						Map.Entry entry = it.next();
						newVal.put(entry.getKey(), toVO(entry.getValue(),
								subSelector));
					}
					ReflectionUtils.setProperty(newObject, prop, newVal);
					// metadata.setPropertyValue(newObject, prop, newVal,
					// EntityMode.POJO);
					continue;
				}
				// 备注 bagType和List相同处理
				if (propType instanceof BagType) {
					List listVal = (List) propVal;
					if (listVal.size() == 0)
						continue;
					List<Object> newVal = new ArrayList<Object>(listVal
							.size());
					for (Iterator it = listVal.iterator(); it.hasNext(); ) {
						newVal.add(toVO(it.next(), subSelector));
					}
					ReflectionUtils.setProperty(newObject, prop, newVal);
					// metadata.setPropertyValue(newObject, prop, newVal,
					// EntityMode.POJO);
					continue;
				}
				// 数组型的属性
				if (propType instanceof ArrayType) {
					Object[] arrVal = (Object[]) propVal;
					if (arrVal.length == 0)
						continue;
					Object[] newVal = new Object[arrVal.length];
					for (int j = 0; j < arrVal.length; j++) {
						newVal[j] = toVO(arrVal[j], subSelector);
					}
					ReflectionUtils.setProperty(newObject, prop, newVal);
					// metadata.setPropertyValue(newObject, prop, newVal,
					// EntityMode.POJO);
					continue;
				}
			}
		}

	} catch (InstantiationException e) {
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	}
	return newObject;
}

  下面是selector类

 

import java.util.HashSet;

/**
 * 属性选择器
 *
 * @author XXX
 * @version 1.0
 */
public class Selector extends HashSet<String> {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	public Selector() {
		super();
	}

	public Selector(int initialCapacity) {
		super(initialCapacity);
	}

	/**
	 * 根据属性,生成子选择器
	 *
	 * @param property
	 * @return
	 */
	public Selector generateSubSelector(String property) {
		Selector subSelector = new Selector();
		for (String s : this) {
			if (s.contains(property)) {
				subSelector.add(s.substring(property.length() + 1, s.length()));
			}
		}
		return subSelector;
	}

	/**
	 * 判断选择器中是否包含属性
	 *
	 * @param property
	 * @return
	 */
	public boolean containsProperty(String property) {
		for (String s : this) {
			if (s.contains("." + property))
				return true;
		}
		return false;
	}

}

 这个是封装方法

 

/**
 * 根据主键、属性字段选择器查找(仅用于查询,结果集已经处于脱管状态)
 *
 * @param id       主键
 * @param selector 属性选择器
 * @return
 */
public final T loadForReview(final Serializable id, final Selector selector) {
	T persistObj = (T) getHibernateTemplate().get(entityClass, id);
	if (persistObj == null) {
		return null;
	}
	return toVO(persistObj, selector);
}

 

   最后是这么调用的

 

Selector selector = new Selector();
selector.add(".vehicleDetail");
vehicleDao.loadForReview(model.getVehicle().getId(), selector);

   这次查询需要什么关联对象,在选择器里面增加就行了,还能增加多个。方便快捷,如果配合缓存,速度大大提升。

 

 

0 请登录后投票
   发表时间:2011-07-08  
这个问题也是讨论过很多次啦,做小弟的,关键还是看头的爱好。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics