在一次使用了SSH的项目中,使用了hibernate逆向工程来生成POJO类和DAO类,非常的方便,但是刚开始使用的时候发现了一些小问题。
1.逆向工程自动生成的POJO类。
Hibernate可以根据每个不同的表的每个字段生成相应的属性。
如下:
public class Account extends com.common.bean.BasePojo implements java.io.Serializable { // Fields private Integer acId; private String acAccount; private String acPass; private Role role; private Date acLastTime; private Set peopleAccounts = new HashSet(0); // Constructors .... // Property accessors .... }
省去部分方法,role属性为Role表的外键,peopleAccounts为其他表外键的集合。对应的hbm.xml表
.... <many-to-one name="role" class=text.Account" fetch="select"> <column name="roleId" not-null="true"> <comment>权限ID</comment> </column> </many-to-one> <set name="peopleAccounts" inverse="true"> <key> <column name="AC_ID"> <comment>帐号密码ID</comment> </column> </key> <one-to-many class="text.PeopleAccount" /> </set>
在这个POJO类和XML表中,逆向工程帮我们生成好了所有的属性,但是这也包括了一些我们不一定需要的属性。假设当前对象为A对象,set集合存放的是所有引用A对象的其它对象的集合,用B集合代替,B集合中的每一个对象都还会持有一个A对象,然后就是这样互相持有下去。如果需要将A对象转成json进行数据传输的话,一不小心就会出现大量冗余数据,甚至是
java.lang.StackOverflowError java.lang.Class.getClassLoader(Class.java:609) java.lang.Package.getPackage(Package.java:330) java.lang.Class.getPackage(Class.java:717) org.json.JSONObject.populateInternalMap(JSONObject.java:357) org.json.JSONObject.<init>(JSONObject.java:310) org.json.JSONObject.populateInternalMap(JSONObject.java:361) org.json.JSONObject.<init>(JSONObject.java:310)
爆栈了,也有可能是这里将设置了lazy="false"的原因。下次在讨论下懒加载机制。
所以一般情况下如果不是特别需要的话可以选择将这个A类中和xml表中的set集合去掉。
当然,如果需要在A对象里保持这个set集,那么我知道的方法一个就算将set集里面A对象的持有置空。(其他人有什么好的方法处理欢迎留言讨论。)
2.逆向工程生成的DAO类
public class AccountDAO extends HibernateDaoSupport { private static final Logger log = LoggerFactory.getLogger(AccountDAO.class); // property constants public static final String AC_ACCOUNT = "acAccount"; public static final String AC_PASS = "acPass"; protected void initDao() { // do nothing } public void save(Account transientInstance) { log.debug("saving Account instance"); try { getHibernateTemplate().save(transientInstance); log.debug("save successful"); } catch (RuntimeException re) { log.error("save failed", re); throw re; } } public void delete(Account persistentInstance) { .... } public Account findById(java.lang.Integer id) { .... } public List findByExample(Account instance) { .... } public List findByProperty(String propertyName, Object value) { .... } public List findByAcAccount(Object acAccount) { return findByProperty(AC_ACCOUNT, acAccount); } public List findByAcPass(Object acPass) { return findByProperty(AC_PASS, acPass); } public List findAll() { .... } /** * 将传入的游离态的对象的属性复制到持久化对象中,并返回该持久化对象。 * 如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回, *传入对象依然保持游离态。 */ public Account merge(Account detachedInstance) { log.debug("merging Account instance"); try { Account result = (Account) getHibernateTemplate().merge( detachedInstance); log.debug("merge successful"); return result; } catch (RuntimeException re) { log.error("merge failed", re); throw re; } } /** * 将传入的对象持久化并保存。 * 如果对象处于瞬时态,调用save方法保存。如果对象处于游离态,调用update方法将对象与Session重新关联。 */ public void attachDirty(Account instance) { log.debug("attaching dirty Account instance"); try { getHibernateTemplate().saveOrUpdate(instance); log.debug("attach successful"); } catch (RuntimeException re) { log.error("attach failed", re); throw re; } } /** * 将传入的对象状态设置为瞬时态 */ public void attachClean(Account instance) { log.debug("attaching clean Account instance"); try { getHibernateTemplate().lock(instance, LockMode.NONE); log.debug("attach successful"); } catch (RuntimeException re) { log.error("attach failed", re); throw re; } } public static AccountDAO getFromApplicationContext(ApplicationContext ctx) { return (AccountDAO) ctx.getBean("AccountDAO"); } }
这是一个标准生成的DAO类,封装了几个基本常用的方法。在任何一个方法中,这个DAO类对数据库的操作都是使用了HibernateTemplate来完成的。所以如果为imen想要调用这些方法的话则需要这样的调用
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountDAO accountDAO = AccountDAO.getFromApplicationContext(ac); accountDAO.XXXX();
因为Hibernate是由Spring托管的,所以需要先加载配置文件,然后根据配置文件中定义好的实体类bean,由Spring的Bean工厂生成DAO类实例。而如果直接new 出这个DAO类对象的话,会使
getHibernateTemplate();
抛出空指针异常。
自动生成的merge(Account detachedInstance), attachDirty(Account instance), attachClean(Account instance)方法作用在注释中给出。
关于ApplicationContext和HibernateTemplate的学习可以参考以下网址
http://www.iteye.com/magazines/72 Spring的源码学习
http://blog.csdn.net/lufeng20/article/details/7314945 HibernateTemplate源码