本讲把Address设计为不可变类.所谓不可变类,是指当创建了这种类的实例后,就不允许修改它的属性.在Java API中,所有的基本类型的包装类,如Integer和Long类,都是不可变类,java.lang.String也是不可变类.在创建用户自己的不可变类时,可以考虑采用以下的设计模式.
a.把属性定义为private final类型.
b.不对外公开用于修改属性的setXXX()方法.
c.只对外公开用于读取属性的getXXX()方法.
d.允许在构造函数中设置所有属性.
e.覆盖Object类的equals()和hashCode()方法
例1:
package mypack;
/**
* @author lfm
*
*/
import java.io.Serializable;
public class Address implements Serializable {
private final String province;
private final String city;
private final String street;
private final String zipcode;
public Address(String province, String city, String street, String zipcode) {
this.province = province;
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
public String getProvince() {
return this.province;
}
public String getCity() {
return this.city;
}
public String getStreet() {
return this.street;
}
public String getZipcode() {
return this.zipcode;
}
public boolean equals(Object o) {
if (this == null || !(o instanceof Address))
return false;
final Address address = (Address) o;
if (!province.equals(address.province))
return false;
if (!city.equals(address.city))
return false;
if (!street.equals(address.street))
return false;
if (!zipcode.equals(address.zipcode))
return false;
return true;
}
public int hashCode() {
int result;
result = (province == null ? 0 : province.hashCode());
result = 29 * result + (city == null ? 0 : city.hashCode());
result = 29 * result + (street == null ? 0 : street.hashCode());
result = 29 * result + (zipcode == null ? 0 : zipcode.hashCode());
return result;
}
}
由于Address类是不可变类,因此创建了Address类的实例后,就无法修改它的属性.如果要修改属性,必须使它引用一个新的Address实例.
例2是AddressUserType的源程序,它实现了UserType接口:
例2:
package mypack;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.UserType;
/**
* @author lfm
*
*/
public class AddressUserType implements UserType {
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#sqlTypes()
*/
public int[] sqlTypes() {
// TODO 自动生成方法存根
return new int[]{Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR};
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#returnedClass()
*/
public Class returnedClass() {
// TODO 自动生成方法存根
return Address.class;
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
*/
public boolean equals(Object x, Object y) throws HibernateException {
// TODO 自动生成方法存根
if(x == y)
return true;
if(x == null || y == null)
return false;
return x.equals(y);
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
*/
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
// TODO 自动生成方法存根
if(rs.wasNull())
return null;
String province = rs.getString(names[0]);
String city = rs.getString(names[1]);
String street = rs.getString(names[2]);
String zipcode = rs.getString(names[3]);
return new Address(province, city, street, zipcode);
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
*/
public void nullSafeSet(PreparedStatement statement, Object value, int index)
throws HibernateException, SQLException {
// TODO 自动生成方法存根
if(value == null) {
statement.setNull(index, Types.VARCHAR);
statement.setNull(index + 1, Types.VARCHAR);
statement.setNull(index + 2, Types.VARCHAR);
statement.setNull(index + 3, Types.VARCHAR);
}else{
Address obj = (Address)value;
statement.setString(index, obj.getProvince());
statement.setString(index + 1, obj.getCity());
statement.setString(index + 2, obj.getStreet());
statement.setString(index + 3, obj.getZipcode());
}
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
*/
public Object deepCopy(Object value) throws HibernateException {
// TODO 自动生成方法存根
return value;
}
/* (非 Javadoc)
* @see net.sf.hibernate.UserType#isMutable()
*/
public boolean isMutable() {
// TODO 自动生成方法存根
return false;
}
}
创建了以上的AddressUserType后,就可以按以下方式映射属性了:
<property name="address" type="mypack.AddressUserType">
<column name="HOME_STREET" length="15"/>
<column name="HOME_CITY" length="15"/>
<column name="HOME_PROVINCE" length="15"/>
<column name="HOME_ZIPCODE" length="6"/>
</property>
Hibernate组件和用户自定义类型都是值类型,在某些情况下能够完成同样的功能,到底选择何种方式,取决于用户自己的喜好.总的来说,Hibernate组件采用的是XML配置方式,因此具有较好的可维护性.自定义类型采用的是编程方式,能够完成更加复杂灵活的映射.
分享到:
相关推荐
在Hibernate 4.0版本中,`hibernate-mapping-4.0.xsd`和`hibernate-configuration-4.0.xsd`分别取代了之前的DTD文件,用以规范和验证新的XML配置文件。`hibernate-mapping-4.0.xsd`包含关于如何定义实体、关联...
3.0版本是Hibernate的一个重大升级,它引入了HQL(Hibernate Query Language),提供了更强大的查询功能,支持CGLIB和JPA(Java Persistence API),并且对JDK 1.5的特性如枚举类型和注解有了更好的支持。...
【SSH 框架简介】 SSH(Struts + Spring + Hibernate)是一种常见的Java Web开发框架组合,...这种组合在过去的Java Web开发中非常流行,但现在已被Spring Boot等现代框架所取代,尽管SSH仍然在许多遗留系统中使用。
本篇文章将探讨如何使用Acegi、Spring、Hibernate和Struts2这四大组件共同构建一个基于角色的权限控制系统(Role-Based Access Control, RBAC),以确保系统的安全性。 首先,我们需要理解认证和授权这两个基本的...
通过iBATIS,开发者可以自定义SQL语句,更好地控制数据库操作。 这三个组件的结合使得SSH成为一个强大的开发工具,它们之间的协作能够有效地解耦业务逻辑和数据访问层,提高代码的可维护性和可扩展性。Struts2负责...
Hibernate 可以应用在任何使用 JDBC 的场合,既可以在 Java 的客户端程序实用,也可以在 Servlet/JSP的 Web 应用中使用,最具革命意义的是,Hibernate 可以在应用 EJB 的 J2EE 架构中取代 CMP,完成数据持久化的重任...
它能够将Struts2和Hibernate整合在一起,使得各组件之间的依赖关系变得更加清晰和解耦。Spring还提供了事务管理功能,可以方便地控制数据库操作的事务边界。 Hibernate是一个对象关系映射(ORM)框架,它简化了Java...
Struts2引入了拦截器(Interceptor)的概念,允许开发者自定义处理流程,增强了灵活性。此外,它支持多种结果类型和模板技术,如JSP、FreeMarker等,使得视图层的实现更加多样。 2. **Spring**:Spring框架是整个...
Struts2提供了拦截器机制,可以自定义拦截器实现如权限验证、日志记录等功能,增强了框架的扩展性。 **Spring** 是一个全面的后端应用框架,它包含了依赖注入(DI)、面向切面编程(AOP)、事务管理、数据访问等...
Struts2还引入了拦截器机制,允许自定义行为,如验证、日志记录等,增强了系统的灵活性和可扩展性。 3. Hibernate框架:Hibernate是一个对象关系映射(ORM)框架,它简化了Java应用程序对数据库的操作。通过...
此外,它还支持多种视图技术,如JSP、FreeMarker、Velocity等,以及丰富的结果类型和国际化功能。 **Spring**: Spring是一个全面的Java企业级应用框架,核心特性包括依赖注入(DI)和面向切面编程(AOP)。DI使得...
此外,熟练掌握Interceptor的编写,能够自定义业务逻辑前后的处理,以及在Hibernate中使用Criteria API进行复杂查询也是必不可少的技能。 在实际开发中,SSH框架的API结合使用,可以实现松耦合、模块化的代码结构,...
在SSH2架构中,Spring负责协调Struts和Hibernate,提供事务管理、DAO工厂、以及业务服务组件的生命周期管理。 3. **Hibernate**:Hibernate是一个对象关系映射(ORM)框架,简化了Java与数据库的交互。它封装了JDBC...
Hibernate则是SSH中的持久化层组件,是一个强大的ORM(对象关系映射)框架。Hibernate允许开发者使用Java对象来操作数据库,而无需直接编写SQL语句,极大地提高了开发效率。它支持多种数据库,包括Oracle、MySQL等,...
Spring框架是SSH的核心,它不仅提供了DI功能,使得对象之间的依赖关系可以通过配置文件进行管理,降低了组件之间的耦合度,还支持AOP,用于实现如事务管理、权限控制等功能。Spring还能集成其他框架,如MyBatis,...
Struts 提供了一个名为 `Converter` 的接口,用于自定义类型的转换规则。当请求参数需要被赋值到 ActionForm 或 Command 对象的属性时,Struts 会尝试使用默认的或用户定义的转换器来进行转换。如果转换失败,Struts...
在SSH整合中,Spring主要负责管理应用的业务层和数据访问层组件,通过DI来控制对象的创建和装配,降低组件间的耦合度。同时,Spring的AOP模块可以用于事务管理,实现声明式事务处理,确保数据的一致性。 2. **...
Spring是核心,它提供依赖注入(DI)和面向切面编程(AOP)的功能,用于管理应用程序的组件。在SSH框架中,Spring主要负责控制层和业务层的事务管理,同时作为数据访问层与其它两层之间的桥梁。 Struts2是SSH中的...
SSHM框架是Spring、...然而,随着微服务架构的兴起,单一的大型框架逐渐被一系列轻量级组件取代,如Spring Boot和Spring Cloud。尽管如此,理解SSHM框架仍然是了解Java Web开发历程和学习现代框架基础的重要步骤。
在SSH系统中,Spring主要负责管理各个组件之间的依赖关系,实现业务逻辑与数据访问层的解耦,同时也提供事务管理和数据源管理等功能。 2. Struts框架: Struts是一个基于MVC(Model-View-Controller)设计模式的...