锁定老帖子 主题:hibernate在新项目上应用的弊端
该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-04-29
关于hql不能实现整个系统的要求,我们项目就有如下要求。
系统需要生成各种报表,包括销售、价格、库存、财务等待,这些报表都很复杂,我们的大部分SQL都超出了4000字符。 我们采用的方式是SQL同一管理,现在然后在代码中同一引用,这样方便管理,数据库有变化,则修改SQL和hibernate的配置文件即可。 关于同时管理hql和sql导致维护成本提高问题: 我还参加了另外一个老项目的修改,这个项目也是hibernate实现,但是也是有复杂SQL直接写在代码中,这时候数据库有变化了,我就得到代码中找相应的SQL修改,同时还有修改hibernate配置文件,当然这个和系统本身的SQL没统一管理有直接关系 |
|
返回顶楼 | |
发表时间:2011-04-29
关于hibernate的效率问题,我对hibernate生成的SQL太长很不爽,而且一个插入语句经常要生生成两个SQL,一个是select一个是insert语句,也不爽。
另外用我只是要查询一个表的数据,往往会查询了多个其他相关的表,当然了如果设置成lazy=true就可解决,但是这时候我们设计代码就得多考虑一下这个表示不是要用lazy呢?这必然导致成本提高。 当然了,以上也是我个人hibernate水平不高导致,欢迎拍砖 |
|
返回顶楼 | |
发表时间:2011-04-29
newslxw 写道 java_bigniu 写道 用了hibernate还老想着这表那表的,难怪了
真正的hibernate高手脑子中式没有表这个东西的 都是对象,考虑的是对象和对象之间的关系 我不赞同一对象方式设计数据库,目前主流数据库都是关系数据库,并不适合使用对象方式设计,个人影响,对象方式设计数据库的系统效率不高。 所以我使用hibernate时,还是先以关系方式设计数据库,根据需求、功能、模型设计数据库,然后再生成hibernate的pojo和xml 我们老大也是先设计表,再用hibernate,我感觉他本末倒置了 另: xml在我们项目组是坚决禁止使用的 当有N个实体类的时候,配置文件太多了 我们都用annotation |
|
返回顶楼 | |
发表时间:2011-04-29
java_bigniu 写道 newslxw 写道 java_bigniu 写道 用了hibernate还老想着这表那表的,难怪了
真正的hibernate高手脑子中式没有表这个东西的 都是对象,考虑的是对象和对象之间的关系 我不赞同一对象方式设计数据库,目前主流数据库都是关系数据库,并不适合使用对象方式设计,个人影响,对象方式设计数据库的系统效率不高。 所以我使用hibernate时,还是先以关系方式设计数据库,根据需求、功能、模型设计数据库,然后再生成hibernate的pojo和xml 我们老大也是先设计表,再用hibernate,我感觉他本末倒置了 另: xml在我们项目组是坚决禁止使用的 当有N个实体类的时候,配置文件太多了 我们都用annotation 是啊,xml多了很难管理,但是用annotation也出现同样的问题,甚至我还不知道那里用到了什么关系,对全局review和统计代码带来很多不便 |
|
返回顶楼 | |
发表时间:2011-04-29
hibernate 我从来没有用过,我只用ibatis
|
|
返回顶楼 | |
发表时间:2011-04-29
newslxw 写道 1、lazy加载,经常带来问题 我也遇到过 session开关不知道在哪儿比较妥当 |
|
返回顶楼 | |
发表时间:2011-05-13
凡是盲目崇拜Hibernate的都是傻X,Hibernate本身也是傻X,又要求数据库结构设计怎样怎样,又要求类设计怎样怎样,什么都按你的设计来,你还不如直接生成应用程序算了!
|
|
返回顶楼 | |
发表时间:2011-05-14
话说 好像没有什么框架是十全十美的!
|
|
返回顶楼 | |
发表时间:2011-07-05
最后修改:2012-03-01
assdust110 写道
nishijia 写道
弱弱地问一下,lazy加载的问题 该如何解决? 我曾经听过一个多年的架构师用hibernate,遇到lazy加载的时候session关闭的问题,最后只好关掉lazy
你那个问题应该是struts+hibernate集成的时候(或类似的框架集成),在控制器中关闭了hibernate的session,而后在页面中你又要迭代对象集合,结果对象集合中的A对象包含了B对象的实体在被访问的时候出现了session关闭的问题,不知是不是这样理解的?这个问题产生的根源其实你去想想程序执行的流程就可以了,用spring,用filter都可以解决这个问题。
/** * 从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); 这次查询需要什么关联对象,在选择器里面增加就行了,还能增加多个。方便快捷,如果配合缓存,速度大大提升。
|
|
返回顶楼 | |
发表时间:2011-07-08
这个问题也是讨论过很多次啦,做小弟的,关键还是看头的爱好。
|
|
返回顶楼 | |