数据库中存在一个email字段,并允许其中存储多个email地址,各地址之间使用 ; 分割,但是在POJO中,为了便于处理,email定义为一个List对象。
如何将String字段映射为List类型,Hibernate并没有提供原生支持,需要我们实现自己的UserType。
1.数据库定义
DROP TABLE t_user;
CREATE TABLE t_user (
id INT NOT NULL AUTO_INCREMENT
, name VARCHAR ( 50 )
, age INT
, email VARCHAR ( 300 )
, PRIMARY KEY (id)
);
2.实现了UserType的自定义数据类型类EmailList
package tuser;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public class EmailList implements UserType {
private static final char SPLITTER = ';';
private static final int[] TYPES = new int[]{Types.VARCHAR};
@Override
public int[] sqlTypes() {
return TYPES;
}
@Override
public Class returnedClass() {
return List.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if(x == y){
return true;
}
if(x != null && y != null){
List xList = (List)x;
List yList = (List)y;
if(xList.size() != yList.size()){
return false;
}
for(int index = 0; index < xList.size(); index++){
String str1 = (String) xList.get(index);
String str2 = (String) yList.get(index);
if(str1 != str2){
return false;
}
}
return true;
}
return false;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
String value = Hibernate.STRING.nullSafeGet(rs, names[0]);
if(value != null){
return parse(value);
}else{
return null;
}
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
System.out.println("Set method executed");
if(value != null){
String str = assemble((List)value);
Hibernate.STRING.nullSafeSet(st, str, index);
}else{
Hibernate.STRING.nullSafeSet(st, null, index);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
List sourceList = (List)value;
List targetList = new ArrayList();
targetList.addAll(sourceList);
return targetList;
}
@Override
public boolean isMutable() {
return false;
}
/**
* 将String拼装为一个字符串,以“;”分隔
* @param emailList
* @return
*/
private String assemble(List emailList){
StringBuffer strBuf = new StringBuffer();
for(int i = 0; i < emailList.size() - 1; i++){
strBuf.append(emailList.get(i)).append(SPLITTER);
}
strBuf.append(emailList.get(emailList.size() - 1));
return strBuf.toString();
}
/**
* 将以“;”分隔的字符串解析为一个字符串数组
* @param value
* @return
*/
private List parse(String value){
String[] strs = value.split(SPLITTER + "");
List emailList = new ArrayList();
for(int i = 0; i < strs.length; i++){
emailList.add(strs[i]);
}
return emailList;
}
@Override
public Object assemble(Serializable arg0, Object arg1)
throws HibernateException {
return null;
}
@Override
public Serializable disassemble(Object arg0) throws HibernateException {
return null;
}
@Override
public int hashCode(Object arg0) throws HibernateException {
return 0;
}
@Override
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
return null;
}
}
3.配置文件TUser.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="tuser.TUser" table="T_USER">
<id name="id" type="java.lang.Integer">
<column name="ID"/>
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="NAME"/>
</property>
<property name="age" type="java.lang.String">
<column name="AGE"/>
</property>
<property name="email" type="tuser.EmailList">
<column name="EMAIL"/>
</property>
</class>
</hibernate-mapping>
4.在hibernate.cfg.xml载入TUser.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<property name="connection.username">
root
</property>
<property name="connection.password">
system
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="javax.persistence.validation.mode">
none
</property>
<property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">20</property>
<property name="c3p0.timeout">300</property>
<property name="c3p0.max_statements">50</property>
<property name="c3p0.idle_test_period">3000</property>
<property name="show_sql">false</property>
<property name="format_sql">false</property>
<mapping resource="hello/Message.hbm.xml"/>
<mapping resource="user/User.hbm.xml"/>
<mapping resource="tuser/TUser.hbm.xml"/>
</session-factory>
</hibernate-configuration>
5.测试类HibernateTest.java
package test;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import tuser.TUser;
import user.User;
public class HibernateTest extends TestCase {
Session session = null;
@Before
protected void setUp() throws Exception {
try {
Configuration configure = new Configuration().configure();
SessionFactory sessionFactory = configure.buildSessionFactory();
session = sessionFactory.openSession();
} catch (HibernateException e) {
e.printStackTrace();
}
}
@After
protected void tearDown() throws Exception {
try {
session.close();
} catch (HibernateException e) {
e.printStackTrace();
}
}
@Test
public void testTUser(){
Transaction tran = null;
try {
tran = session.beginTransaction();
TUser user = new TUser();
user.setName("byf");
List list = new ArrayList();
list.add("baiyf@msn.com");
list.add("bexy@163.com");
user.setEmail(list);
session.save(user);
session.flush();
tran.commit();
Assert.assertEquals(user.getId().intValue()>0 ,true);
} catch (HibernateException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
if(tran != null) {
try {
tran.rollback();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
/**
* 对象读取测试(Select方法)
*/
public void testSelect(){
String hql = " from TUser where name='byf'";
try {
List userList = session.createQuery(hql).list();
TUser user = (TUser)userList.get(0);
List mailList = user.getEmail();
Assert.assertEquals((String)mailList.get(0), "baiyf@msn.com");
Assert.assertEquals((String)mailList.get(1), "bexy@163.com");
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
}
6.TUser类
package tuser;
import java.io.Serializable;
import java.util.List;
public class TUser implements Serializable {
private static final long serialVersionUID = 1901560971512450430L;
private Integer id;
private String name;
private Integer age;
private List email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List getEmail() {
return email;
}
public void setEmail(List email) {
this.email = email;
}
}
运行测试代码,观察数据库中,可以发现email地址信息已经以";"分隔的形式保存。同时,在数据读取时,我们也无需面对原始的";"分隔字符串,转而只需要处理List类型数据即可。
分享到:
相关推荐
在Oracle中,一个基于...3D模型在Oracle 11g空间数据中存储和建模,也开发了2个自定义Java类来映射Oracle 11g空间类型中的SDO_GEOMETRY数据类型,用于解决Hibernate目前不支持对SDO_GEOMETRY数据类型进行映射的问题。
1.4 Hibernate自定义类型 对象--->序列化为字符串 存储 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.5 Hibernate自定义类型 集合--->字符串 存储 . . . . . . . . . . . . . . ....
1.4 Hibernate自定义类型 对象--->序列化为字符串 存储 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48 1.5 Hibernate自定义类型 集合--->字符串 存储 . . . . . . . . . . . . ...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...
Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 持久化枚举(Persistent enum)类型 5.2.4. 自定义值类型 5.2.5. 映射到"任意"(any)类型 5.3. SQL中引号包围...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...
5.2.3. 自定义值类型 5.3. SQL中引号包围的标识符 5.4. 其他元数据(Metadata) 5.4.1. 使用 XDoclet 标记 5.4.2. 使用 JDK 5.0 的注解(Annotation) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...
自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...
6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...
Collection类型属性中 <br>............... <br> ............... <br> 27.Spring的参数化事务管理功能相当强大,笔者建议在基于Spring Framework的应用 开发中,尽量使用容器管理事务,以获得...
Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 持久化枚举(Persistent enum)类型 5.2.4. 自定义值类型 5.2.5. 映射到"任意"(any)类型 5.3. SQL中引号包围...
6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...
5.2.3. 自定义值类型 5.3. SQL中引号包围的标识符 5.4. 其他元数据(Metadata) 5.4.1. 使用 XDoclet 标记 5.4.2. 使用 JDK 5.0 的注解(Annotation) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...
自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...
6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...
5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...