Hibernate自定义数据类型
程序员文章站
2022-06-07 18:48:48
...
转载出处:https://blog.csdn.net/u012607848/article/details/54089120
Hibernate对一些基本类型的映射提供了很好的支持,但有时候我们需要映射自定义或更复杂的数据类型,比如一个List集合,可以通过基本类型映射实现,需要在数据库中新建一张表,这种方式增加了数据库开销;也可以将List集合中的数据拼接成字符串再存储,这种方式导致程序可读性不友好,同时增加代码的复杂度;Hibernate提供了DiscriminatorType
和UserType
接口,方便用户自定义需要映射的数据类型。这里以UserType为例实现。
假设用户需要自定义一个类型,名称为ctype
,它是16位字符的char
数组,需要映射到数据库VARCHAR
类型。
首先自定义 java 类型ctype
:
public class ctype implements Serializable {
// mtype 的长度
private static int TYPE_LENGTH = 16;
// mtype 实际上就是 char 数组
private char[] mtype = new char[TYPE_LENGTH];
// 默认构造函数
public ctype() {
this.mtype = new char[0];
}
// 通过构造函数转换为ctype类型
public ctype(Object object) {
String str = String.valueOf(object);
if (StrUtil.isBlank(str))
this.mtype = new char[0];
this.mtype = str.toCharArray();
}
public boolean isEmpty() {
return String.valueOf(this.mtype).replace(" ", "").length() < TYPE_LENGTH;
}
public String toString() {
return String.valueOf(this.mtype);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ctype ctype = (ctype) o;
return Arrays.equals(mtype, ctype.mtype);
}
@Override
public int hashCode() {
return Arrays.hashCode(mtype);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
接下来实现Hibernate UserType
接口:
/**
* Hibernate自定义类型
*/
public class customType implements UserType {
private static int[] TYPES = new int[]{Types.VARCHAR};
/**
* 修改类型对应的SQL类型(这里用VARCHAR
*/
@Override
public int[] sqlTypes() {
return TYPES;
}
/**
* 修改customType对应的java类型(此处java类型为ctype
*/
@Override
public Class returnedClass() {
return ctype.class;
}
/**
* 自定义数据类型比对方法
* 用作脏数据检查,o,o1为两个副本
*/
@Override
public boolean equals(Object o, Object o1) throws HibernateException {
return Objects.equals(o, o1);
}
/**
* 返回给定类型的hashCode
*/
@Override
public int hashCode(Object o) throws HibernateException {
return Objects.hashCode(o);
}
/**
* 读取数据转换为自定义类型返回
* strings包含了自定义类型的映射字段名称
*/
@Override
public Object nullSafeGet(ResultSet resultSet, String[] strings,
SessionImplementor sessionImplementor, Object o)
throws HibernateException, SQLException {
String s = (String) resultSet.getObject(strings[0]);
if (resultSet.wasNull()) return null;
if (null != s) {
if (s.replaceAll(" ", "").isEmpty())
return null;
return new ctype(s);
}
return null;
}
/**
* 数据保存时被调用
*/
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i,
SessionImplementor sessionImplementor)
throws HibernateException, SQLException {
if (null == o) {
preparedStatement.setNull(i, Types.VARCHAR); //保存空值
} else {
String stringValue = String.valueOf(o);
preparedStatement.setString(i, stringValue);
}
}
/**
* 自定义类型的完全复制方法,构造返回对象
* 1. 当nullSafeGet方法调用之后,我们获得了自定义数据对象,
* 在向用户返回自定义数据之前,deepCopy方法被调用,
* 它将根据自定义数据对象构造一个完全拷贝,把拷贝返还给客户使用。
* 2. 此时我们就得到了自定义数据对象的两个版本
* 原始版本由hibernate维护,用作脏数据检查依据;
* 复制版本由用户使用,hibernate将在脏数据检查过程中比较这两个版本的数据;
*/
@Override
public Object deepCopy(Object o) throws HibernateException {
if (o == null) return null;
ctype c = (ctype) o;
ctype nc = new ctype();
nc = c;
return nc;
}
/**
* 表示本类型实例是否可变
*/
@Override
public boolean isMutable() {
return true;
}
/**
* method called when Hibernate puts the data in a second level cache. The
* data is stored in a serializable form (官方文档
*/
@Override
public Serializable disassemble(Object o) throws HibernateException {
return (ctype) deepCopy(o);
}
/**
* Returns the object from the 2 level cache (官方文档
*/
@Override
public Object assemble(Serializable serializable, Object o)
throws HibernateException{
return deepCopy(serializable);
}
@Override
public Object replace(Object o, Object o1, Object o2)
throws HibernateException {
return deepCopy(o);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
通过注解方式使用:
/**
* Entity -> Item
*/
@Entity
@Table(name = "d_item")
@TypeDef(name = "myType", typeClass = customType.class)
public class Item implements Serializable {
@Id
@Type(type = "myType")
private ctype uid;
... ...
}
完成。
上一篇: 太监出一上联,讥讽纪晓岚,纪晓岚机智回应
下一篇: SEO 分享WEB标准对seo产生的影响