论坛中关联的地址:
http://www.iteye.com/topic/397854
直接上代码比较能说明问题。
首先是一个工具类SpringContextTool.java,getIdValue方法原本其他工具类中的方法,挪过来放在一起说方便。虽然是JDK 1.5的编程风格,但是主要技巧同样适用于JDK 1.4。
public class SpringContextTool implements ApplicationContextAware {
/**Spring应用上下文环境*/
private static ApplicationContext applicationContext;
/**实现ApplicationContextAware接口的回调方法,设置上下文环境
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextTool.applicationContext = applicationContext;
}
public static SessionFactory getSessionFactory() {
Assert.notNull(applicationContext, "applicationContext is null,请确保spring容器正常启动");
return (SessionFactory) applicationContext.getBean("sessionFactory");
}
public static ClassMetadata getClassMetadata(Class<?> cls) {
return getSessionFactory().getClassMetadata(cls);
}
/**得到一个model的id的值,可以直接获得id而不触发sql的产生,适合ManyToOne的场景
* @param model 有可能是CGLib增强之后的对象
* @return id
*/
public static String getIdValue(BaseModel model) {
if (model instanceof HibernateProxy) {
return (String) ((HibernateProxy) model).getHibernateLazyInitializer().getIdentifier();
}
return (String) getClassMetadata(model.getClass()).getIdentifier(model, EntityMode.POJO);
}
}
1.这里的applicationContext属性是static的,觉得奇怪吧,没办法啊,为了追求getIdValue是static的,因为Model中或者是BaseModel中实现HashCode或者是equals最好是能调用static的方法,而不是有状态的。
2.getIdValue方法中,参数model可以是Object类型,其中实现方法可以看到,如果是代理对象HibernateProxy,可直接得到他的ID,如果是非代理对象,通过配置信息一样可以得到ID。传入参数可以改成Object类型,返回类型也可以根据需要修改成Object。
下面是我写的BaseModel中的应用(注意hashCode方法的实现,我这里规定ID是String类型的,其他类型的ID一样可以借鉴),仅供参考:
public abstract class BaseModel<E> implements Cloneable, Serializable {
public int hashCode() {
String idStr = SpringContextTool.getIdValue(this);
return idStr == null ? super.hashCode() : idStr.hashCode();
}
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other == this) {
return true;
}
/*因为字节码增强的关系,getClass()不能用作判断的依据*/
if (getClass().getPackage() != other.getClass().getPackage()) {
return false;
}
if (hashCode() == other.hashCode()) {
return true;
}
return false;
}
/**日志对象*/
protected final Logger log = Logger.getLogger(getClass());
/**覆盖toString方法,ToStringStyle取值为ToStringStyle.SHORT_PREFIX_STYLE
* ,调试的时候注意会自动取所有引用的值,会触发所有的Hibernate的延迟加载,
* 如果遇到性能问题,必须覆盖这个默认的toString方法的实现,或者避免调用这个默认的toString方法。
* @return String
*/
public String toString() {
ToStringBuilder tsb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
for (Field field : getClass().getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
String name = field.getName();
if ("log".equals(name) || "serialVersionUID".equals(name)) {
continue;
}
Object obj = ModelUtils.getProperty(this, name);
if (obj instanceof AbstractPersistentCollection) {
continue;
}
if (obj instanceof Calendar) {
obj = DateTimeUtils.calendar2StrDateTime((Calendar) obj);
}
tsb.append(name, obj);
}
return tsb.toString();
}
/**提供默认的clone方法的实现,不支持深层复制
* @return Object
*/
public E clone() {
try {
return (E) super.clone();
} catch (CloneNotSupportedException ex) {
throw new IllegalArgumentException(ex.getMessage());
}
}
/**提供simple的clone方法的实现,不复制Hibernate代理对象
* @return Object
*/
public Object cloneSimple() {
Object obj = ModelUtils.newInstance(getClass());
Field[] fields = getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (Modifier.isStatic(fields[i].getModifiers())) {
continue;
}
String name = fields[i].getName();
if ("serialVersionUID".equals(name)) {
continue;
}
Object fieldObj = ModelUtils.getProperty(this, name);
if (fieldObj instanceof AbstractPersistentCollection ||
fieldObj instanceof BaseModel) {
continue;
}
ModelUtils.setProperty(obj, name, fieldObj);
}
return obj;
}
}
分享到:
相关推荐
本文将详细讲解如何使用Hibernate来编写通用的数据库操作代码,包括插入(insert)、删除(delete)、更新(update)以及查询(select)方法。 1. 插入数据(insert) 插入数据的方法是通过调用`session.save()`...
这些方法展示了如何在 Hibernate 中进行基本的 CRUD(创建、读取、更新、删除)操作,它们是任何使用 Hibernate 的项目中的基础组成部分。通过封装这些通用方法,可以提高代码的可重用性和可维护性,减少重复的工作...
`DaoUtil`类初始化了一个`SessionFactory`实例,并提供了一个获取`Session`的静态方法,方便在DAO实现类中使用。 总的来说,"Hibernate泛型DAO接口,大部分通用都已包括"意味着我们已经定义了一套完整的、适用于多...
- **更新实体**:使用`update()`方法更新数据库中的记录,通常需要先通过`get()`方法获取要更新的对象。 - **删除实体**:`delete()`方法根据给定的ID删除数据库中的记录。 - **查询实体**:提供`findById()`方法...
**hibernate通用DAO(Data Access Object)**是软件开发中的一个重要概念,它主要用于数据库操作的抽象,使得业务逻辑层可以无需关注具体的SQL语句,从而实现数据访问的解耦。在Java EE应用中,Hibernate作为一款...
此外,通用分页是Web应用中常见的需求,可以使用Spring JPA的`Pageable`接口或者自定义分页查询方法来实现。通过传递页码和每页大小,可以轻松获取数据的指定部分,同时获取总页数等信息,提升用户浏览大量数据时的...
- **SessionFactory**:`HibernateSessionFactory.getSession()`方法用于获取`Session`实例,这通常是在配置文件中定义好的`SessionFactory`的工厂方法。 - **事务管理**:在每个操作方法中都涉及到事务的提交...
`getCurrentSession()`获取当前的数据库会话,`get()`方法根据ID从数据库加载对应实体。 为了使这个公共类更具通用性,通常还需要定义一个基类,如`BaseEntity`,所有实体类都继承自它。这样,`EntityDao`接口和`...
- `findById(ID id)`: 根据ID查找实体,对应Hibernate的`Session.get()`。 - `findAll()`: 获取所有实体,对应Hibernate的`Session.createCriteria().list()`。 - `count()`: 计算实体总数,通常使用`Session....
而泛型DAO(Data Access Object)则是基于Hibernate进一步抽象出来的一个设计模式,用于提供更通用的数据操作方法。本文档主要探讨了如何在Spring+Hibernate环境中创建和使用泛型DAO。 首先,我们来看一下泛型DAO...
- `getById()`:根据ID获取对象,通常使用`Session.get()`或`Session.load()`方法。 - `queryAll()`:查询所有对象,可能需要结合`Criteria`或`HQL`(Hibernate Query Language)实现。 - `queryByCondition()`:...
UUID (通用唯一标识符) 是一种生成全局唯一 ID 的方法,适合于分布式系统。 #### 结语 以上内容涵盖了 Hibernate 的入门、进阶和高级主题,旨在帮助开发者全面掌握 Hibernate 的使用技巧。通过这些章节的学习,...
这个基类会包含一些通用的CRUD(Create, Read, Update, Delete)方法,如`save(T entity)`用于保存对象,`getById(ID id)`用于根据ID获取对象等。然后,对于每个实体类,你只需要创建一个接口,继承自`...
4. **加载(Load)**:`getById(ID id)` 方法用于根据主键ID获取数据库中的对象。通常,这会调用`Session.get()`来查找并返回对应的实体。 5. **查询(Query)**:BaseDAO可能还包含了更复杂的查询功能,如`...
例如,`save()`用于保存对象,`getById()`用于根据ID获取对象,`update()`用于更新对象,`deleteById()`用于删除对象。 4. **DAO接口与实现**: 创建一个DAO接口,定义所有需要的方法,然后创建一个实现该接口的类...
使用 `session.get()` 或 `session.load()` 方法可以从数据库中获取对象。`get()` 方法在数据不存在时返回 `null`,而 `load()` 会抛出异常。通常情况下,为了防止空指针异常,我们使用 `get()`,但在系统优化时,...
1. **基本查询**:提供一个通用的方法,用于根据ID获取对象,例如`public T findById(Class<T> entityClass, Serializable id)`。这个方法会使用Hibernate的`Session`对象的`get`方法来执行查询。 2. **条件查询**...
基于泛型的通用Dao接口和Hibernate的实现 基于泛型的通用Dao接口是指使用泛型来实现数据访问对象(DAO)的接口,主要是在使用 Hibernate 或 JPA 时使用。泛型可以使得DAO接口更灵活、更通用。 泛型Dao接口的优点:...