使用UserType首先要弄清楚它的目的。大家知道Hibernate解决的主要是对象数据库阻抗失衡的问题,也就是如何将一个或多个对象保存到一个或多个数据库表格中。这其中有很多方法,其实大部分情况下采用
@Embeddable和
@Embedded 就可以解决问题了,只有嵌入对象方式无法满足要求时,或者是Hibernate默认的持久化方式无法满足要求时,才应该考虑UserType。总之记住一 个原则,不到山穷水尽,不要轻易使用UserType。还有一个要慎重考虑使用UserType的原因是:一旦采用了UserType,你的项目就脱离了 JPA,而直接和Hibernate耦合在一起了。
扩展UserType主要分为两种:
- immutable
- mutable
今天我先举个immutable的例子。
Java 5提出了一个新的enum类,JPA提供的标准方法是保存enum的name或者是ordinal。这种默认方式能够满足新开发的项目,但是对于一些老项目翻新并不一定适用。下面我们来看一个例子:
<!---->public
class
Status {
public
static
final
int
ACTIVATED
=
5
;
public
static
final
int
DEACTIVATED
=
6
;
}
这个是在java5之前常用的常量定义方法,老项目数据库里面已经保存了很多的5啊6的。现在要把Status改写成enum,而且不希望修改数据库中已有的数据,怎么做?第一反应,status enum可以这么写:
<!---->public
enum
Status {
ACTIVATED,
DEACTIVATED;
}
持久化enum的name属性是肯定不用考虑了,ordinal属性呢?这里要保存的可是5和6,而Status enum只有两个实体,他们的ordinal只是0和1。而且项目中还会有其他很多类似的常量类需要改写成enum,JPA的默认方式无法完成任务,这时 候可以开始考虑使用UserType了。
先定义一个接口,这样可以使用一个UserType支持所有类似的enum:
<!---->public
interface
DescriptionID {
String getDescription();
int
getId();
}
然后改写Status enum:
<!---->public
enum
Status
implements
DescriptionID {
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:
<!---->@TypeDefs({@TypeDef(name
=
"
status
"
, typeClass
=
DescriptionIDUserType.
class
,
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类。
类似的情况朋友们可以自由发挥了。
相关推荐
1.Configuration.xml 是 mybatis 用来建立 sessionFactory 用的,里面主要包含了数据库连接相关东西,还有 java 类所对应的别名,比如 <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 这个别名...
User Configuration and Slicing 43.3.21. Using Spock to Test Spring Boot Applications 43.4. Test Utilities 43.4.1. ConfigFileApplicationContextInitializer 43.4.2. TestPropertyValues 43.4.3. ...
MTPA数值求解:双法探究,MTPA数值求解详解:两种方法的比较与应用探索,MTPA数值求解两种方法 ,MTPA数值求解; 方法一; 方法二;,MTPA数值求解的两种高效方法
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
'Function 生成视频缩略图(ByVal 视频文件 As String, ByVal 保存缩略图的文件路径 As String, Optional ByVal jpg图像品质 As Long = 80, _ ' Optional ByVal 缩略图宽度 As Long = 500, Optional ByVal 缩略图高度 As Long = 500 _ ' , Optional 返回图像实际宽度 As Long, Optional 返回图像实际高度 As Long) As Boolean Public Function SaveImageAs(LoadImgFile As String, ByVal SaveAsImgFile As String, _ Optional ByVal JpgQuality As Long = 80, Optional hPal As Long, Optional Resolution As Single) As Boolean
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
bkall_answers(2).json
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
近日,一份由清华大学团队发布《DeepSeek:从入门到精通》的AI学习教程冲上了热搜,它是由清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室的余梦珑博士后及其团队倾力打造,从三个方面深入剖析了DeepSeek,DeepSeek是什么?有什么用?怎么使用? 详细论述了其应用场景与使用方法,并讲解了如何通过设计精妙的提示语来提升AI的使用效率,以及丰富的实例干货。 全部104页,完整版资料已经帮大家整理好了,免费领取 资料链接: https://pan.quark.cn/s/be3b500c539c
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
冰点下载器珍藏版.zip
Wallpaper Engine 是一款广受欢迎的动态壁纸软件,允许用户将各种动态、交互式壁纸应用到桌面上。其丰富的创意工坊内容让用户可以轻松下载和分享个性化的壁纸。而“一键提取”功能则是 Wallpaper Engine 中一个非常实用的工具,能够帮助用户快速提取和保存壁纸资源,方便后续使用或分享。
科研人员
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
13考试真题最近的t66.txt
对外承包项目借款合同2[示范文本].doc