在一次使用了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源码