- 浏览: 7339541 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
在项目中许多地方使用枚举类,枚举对象值对应数据一个常量。增加代码的可读性等。具体使用如下:
JPA参考手册:JPA注释参考手册 http://www.oidn.net/blog/article.asp?id=250
Hibernate Annotation 用户类型(User Type)
使用UserType首先要弄清楚它的目的。大家知道Hibernate解决的主要是对象数据库阻抗失衡的问题,也就是如何将一个或多个对象保存到一个或多个数据库表格中。
这其中有很多方法,其实大部分情况下采用@Embeddable和 @Embedded 就可以解决问题了,只有嵌入对象方式无法满足要求时,或者是Hibernate默认的持久化方式无法满足要求时,才应该考虑UserType。
总之记住一 个原则,不到山穷水尽,不要轻易使用UserType。还有一个要慎重考虑使用UserType的原因是:一旦采用了UserType,你的项目就脱离了 JPA,而直接和Hibernate耦合在一起了。
扩展UserType主要分为两种:
- immutable
- mutable
今天我先举个immutable的例子。
Java 5提出了一个新的enum类,JPA提供的标准方法是保存enum的name或者是ordinal。这种默认方式能够满足新开发的项目,但是对于一些老项目翻新并不一定适用。下面我们来看一个例子:
public static final int ACTIVATED = 5 ;
public static final int DEACTIVATED = 6 ;
}
这个是在java5之前常用的常量定义方法,老项目数据库里面已经保存了很多的5啊6的。现在要把Status改写成enum,而且不希望修改数据库中已有的数据,怎么做?第一反应,status enum可以这么写:
ACTIVATED,
DEACTIVATED;
}
持久化enum的name属性是肯定不用考虑了,ordinal属性呢?这里要保存的可是5和6,而Status enum只有两个实体,他们的ordinal只是0和1。而且项目中还会有其他很多类似的常量类需要改写成enum,JPA的默认方式无法完成任务,这时 候可以开始考虑使用UserType了。
先定义一个接口,这样可以使用一个UserType支持所有类似的enum:
String getDescription();
int getId();
}
然后改写Status enum:
ACTIVATED( 5 , " This object is activated " ),
DEACTIVATED( 9 , " This object is deactivated " );
private Integer id;
private String description;
private static List < Status > list;
static {
list = new ArrayList < Status > ( 2 );
list.add(ACTIVATED);
list.add(DEACTIVATED);
}
private Status( int statusNr, String description) {
this .id = statusNr;
this .description = description;
}
public String getDescription() {
return this .description;
}
public Integer getId() {
return id;
}
public static List < Status > getAll() {
return list;
}
public static Status findById(Integer id) {
for (Status status : getAll()) {
if (id == status.getId()) {
return status;
}
}
return null ;
}
}
注意这里每个enum都必须有两个static方法,这些方法名必须在所有的enum中保持一致。
List()方法是为了方便获取所有的Status常 量,例如在用户界面通过ComboBox展示,findById()方法是为了通过给定Id获得对应的Enum实例。其中findById()方法参数一 定要是Integer,原因后面会讲到。
下面编写DescriptionIDUserType:
public class DescriptionIDUserType implements UserType, ParameterizedType {
private Class enumClass;
public void setParameterValues(Properties parameters) {
try {
enumClass = ReflectHelper.classForName(parameters.getProperty( " class " ));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object assemble(Serializable cached, Object arg1)
throws HibernateException {
return cached;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object)
*/
public Object deepCopy(Object value) throws HibernateException {
// TODO Auto-generated method stub
return value;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#disassemble(java.lang.Object)
*/
public Serializable disassemble(Object value) throws HibernateException {
// TODO Auto-generated method stub
return (Serializable) value;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#equals(java.lang.Object,
* java.lang.Object)
*/
public boolean equals(Object id1, Object id2) throws HibernateException {
if (id1 == id2) {
return true ;
}
if (id1 == null || id2 == null ) {
return false ;
}
final DescriptionID did1 = (DescriptionID) id1;
final DescriptionID did2 = (DescriptionID) id2;
return did1.getId() == did2.getId()
&& StringUtils.equals(did1.getDescription(), did2
.getDescription());
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
*/
public int hashCode(Object value) throws HibernateException {
// TODO Auto-generated method stub
return value.hashCode();
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#isMutable()
*/
public boolean isMutable() {
// TODO Auto-generated method stub
return false ;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,
* java.lang.String[], java.lang.Object)
*/
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
throws HibernateException, SQLException {
try {
int id = resultSet.getInt(names[ 0 ]);
if (resultSet.wasNull()) {
return null ;
}
return enumClass.getMethod( " findById " , new Class[] { Integer. class })
.invoke( null , id);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null ;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#nullSafeSet(java.sql.PreparedStatement,
* java.lang.Object, int)
*/
public void nullSafeSet(PreparedStatement statement, Object value, int index)
throws HibernateException, SQLException {
if (value == null ) {
statement.setNull(index, Hibernate.INTEGER.sqlType());
} else {
DescriptionID dID = (DescriptionID) value;
statement.setInt(index, dID.getId());
}
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#replace(java.lang.Object,
* java.lang.Object, java.lang.Object)
*/
public Object replace(Object original, Object arg1, Object arg2)
throws HibernateException {
// TODO Auto-generated method stub
return original;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#returnedClass()
*/
public Class returnedClass() {
return DescriptionID. class ;
}
/*
* (non-Javadoc)
*
* @see org.hibernate.usertype.UserType#sqlTypes()
*/
public int [] sqlTypes() {
return new int []{Hibernate.INTEGER.sqlType()};
}
}
我们的这个UserType是要支持实现DescriptionID的各种不同的enum,而enum是没法继承的。所以我们需要用户给出具体的参数,以进一步确定到底是哪个enum类。这也就导致了,我们的这个类需要实现 ParameterizedType接口。
由于enum类本身是immutable的,所以这个UserType的实现类相对比较简单,主要的两个方法是 nullSafeGet和 nullSafeSet。
在nullSaftGet中我们使用Java Reflection并借助用户给出的enum类参数直接调用该enum类的findById()方法,这样我们就可以使用数据库中的integer找到 对应的enum实例。
注意,由于使用了Java Reflection,所以findById()方法参数必须是Integer而非int。 在nullSafeSet中,我们则通过 DescriptionID接口直接获取enum实例的id属性,并且将它保存到数据库中去。
最后看看怎么使用这个UserType:
parameters = {@Parameter(name = " class " , value = " com.yourpackage.Status " )})})
@Entity
public class SomeObject {
private Integer objectId;
private Status status;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getObjectId() {
return objectId;
}
public void setObjectId(Integer objectId) {
this .objectId = objectId;
}
@Type(type = " status " )
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this .status = status;
}
}
其中值得讲讲的就是定义Type时使用的parameter,"class"参数是我们自己定义的,该参数为DescriptionIDUserType提供 了具体的enum类。前面已经讲过了,DescriptionIDUserType就是在运行时态利用这个参数自定义enum与数据库之间的持久化逻辑。
使用这个UserType之后,我们就可以在确保数据库数据不变的情况下,成功地将类型不保险的常量类改写成enum,而且这个UserType支持所有实现了 DescriptionID接口的enum类。
发表评论
-
编程的十四条经验
2013-05-06 10:32 1821排列不分先后: 1. 当 ... -
整合Struts2+JasperReport Web报表应用示例
2013-04-22 13:56 2289整合Struts2+JasperReport Web报表应用 ... -
关于H2使用的那些事
2012-12-14 16:40 27222在项目中采用H2作为工 ... -
Java 分割功能实现
2011-08-25 08:39 2795在项目针对比较大的文件需要文件的分割功能,特意写了一个 ... -
反射工具类
2010-04-25 10:47 2401package easyway.tbs.client.bm.u ... -
项目中Hibernate中Criteria和Query查询和模式引用
2010-02-21 15:52 2457在项目中Hibernate中Criteria和Q ... -
json 在项目中开发一个巧妙地应用
2009-12-12 16:49 3905在项目中需要保存客户的信息到Cookie中,因为客户要求 ... -
项目中使用时间工具类
2009-11-21 16:43 3035项目中使用的时间工具类的主要的采用commons-l ... -
将HTML文件转换为图片应用开发
2009-10-21 11:15 4466项目使用的基 ... -
Spring项目的测试用例
2009-08-22 12:49 2332在项目的开发过程中使用Junit4测试代码,使用 ... -
jBPM与Spring整合浅析
2009-08-22 12:41 26641、创建公文流转相关的实体类,并创建数据库表 2、根据对用 ... -
Hibernate正向工程hbm2ddl
2009-08-19 10:14 2312一般在项目开 ... -
关于常用城市控件中数据的处理方案
2009-08-15 19:41 2420在项目中由于多次使用的国家省份城市的控件,以前采 ... -
在Spring2.5注解时必须注意几点
2009-08-15 19:22 2137项目中采用Spring2.5配置重点内容如下: ... -
中文转换拼音的实现思路以及实现
2009-08-15 18:40 2918在项目中一位大师兄写的中文转换拼音代码:自己整理一下 ... -
在项目中一些相关常量数组使用枚举应用
2009-08-15 18:01 2622在项目中采用Hibernate中支持枚举类型因此我们使用许 ... -
在项目开发中关于Hibernate注解的配置的一些说明
2009-08-15 13:26 4350在项目开发中采用Hibernate3注解方式实现关 ... -
关于项目中泛型的应用
2009-08-15 12:38 2399在项目采用JDK1.6采用泛型开发,在开发应用之中减少了大 ... -
针对项目中XML解析的扩展应用
2009-08-15 12:14 2580由于项目中多个需 ...
相关推荐
本文将深入探讨Hibernate如何映射枚举类型,并给出实际应用示例。 ### Hibernate枚举映射方式 #### 1. `@Enumerated` 注解 Hibernate通过`@Enumerated`注解来处理枚举映射。这个注解有两个可选的枚举值:`Enum...
在实际应用中,应结合业务场景、数据特性以及性能需求来选择Set、List、Array或Map进行映射,确保数据的一致性和高效性。同时,理解并熟练掌握这些映射方式,能够帮助开发者更好地利用Hibernate进行数据操作。
在这个主题中,我们主要关注的是Hibernate的配置文件`hibernate.properties`以及它的DTD(Document Type Definition)文件,包括`hibernate-configuration-3.0.dtd`和`hibernate-mapping-3.0.dtd`。 首先,`...
这样,Hibernate就能理解User与Phone之间的关联,并在数据库中创建相应的外键关系。 其次,List是一种有序的集合,它对应于数据库中的数组或者序列化的字段。在Hibernate中,我们使用`@OrderColumn`来保持列表中...
Hibernate提供了强大的映射工具和代码生成工具,可以极大地简化Java应用中的数据访问层编程工作。 #### 五、Java实体类(User)设计 在本例中,创建了一个名为`User`的Java实体类,该类包含三个属性:`id`、`name`和...
本文将详细介绍 Hibernate 提供的几种查询方式及其应用场景。 #### 二、重要知识点 ##### 1. Session 对象与查询操作 在 Hibernate 中,所有持久化操作都需要通过 Session 对象来完成,包括查询操作。Session ...
在实际应用中,为了确保数据一致性,我们还需要理解懒加载(Lazy Loading)和急加载(Eager Loading)的概念,以及它们在不同关联关系中的应用。同时,了解级联操作(Cascade Type)如SAVE_UPDATE、PERSIST、REMOVE...
通过以上三个定则的介绍,可以看出Hibernate在实际应用中具有很大的灵活性。合理利用这些特性不仅可以提高开发效率,还能帮助团队更好地管理项目。此外,在结合Struts和Spring等其他框架时,这种灵活性显得尤为重要...
首先,Hibernate是一个强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,简化了Java应用中的数据访问层。在这个案例中,我们首先需要定义一个User实体类,该类代表注册用户的数据模型,通常包含...
**hibernate登录页面测试** Hibernate 是一个流行的Java ORM(对象关系映射)框架,它允许...通过分析这些文件,初学者可以更好地了解如何将Hibernate应用于实际的登录系统中,从而深化对ORM框架和Web开发的理解。
在实际应用中,可能还需要考虑文件上传、下载、流处理等问题,确保高效且安全地处理大数据。 总结来说,Hibernate通过配置文件和实体类实现了对BLOB和CLOB类型的支持,允许开发者在Java代码中方便地操作大数据。...
- 在具体的Action配置中,为输出JSON数据的结果类型加入参数: ```xml <result name="testGetUser" type="json"> <param name="root">jsonResultObj <param name="ignoreHierarchy">false ...
这篇文章将深入探讨Hibernate中的集合映射机制,包括其基本概念、类型以及如何在实际开发中进行配置。 ### 1. Hibernate集合映射的基本概念 集合映射是Hibernate中一个核心的概念,它允许我们将数据库表中的多对一...
在传统的Hibernate应用中,我们通常使用XML文件来描述对象和表之间的映射关系。然而,随着Java 5的发布,注解成为了一种更简洁、更直观的元数据表示方式。Hibernate注解就是利用这种方式,将对象的映射信息直接写在...
然后,Action类会创建一个HttpServletResponse对象,设置响应的Content-Type为图片的MIME类型,如"image/jpeg",并使用Servlet的`write()`方法将图片文件内容写入到HTTP响应流中,最后触发浏览器下载。 安全性和...
然而,当我们面临复杂的数据表结构,尤其是涉及到复合主键时,如何在Hibernate中进行配置和使用就显得尤为重要。本文将深入探讨Hibernate对复合主键的支持,帮助开发者更好地理解和应用这一特性。 一、什么是复合...
以上便是对Hibernate基础的概览,实际开发中,还需要深入了解实体关系映射、集合映射、级联操作、缓存机制、事务管理、性能优化等方面的知识,才能更好地利用Hibernate提升开发效率并保证应用程序的稳定运行。...
**Hibernate Validator** 是一个流行的 Java 验证框架,它实现了 **JSR 349**(即 Java Bean Validation API)规范,提供了强大的验证功能,帮助开发者确保应用程序中的数据符合预定的规则。本文档将详细介绍 **...