- 浏览: 99262 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
蜗居之家:
akka2.0的如何实现1.2的功能 onReceive中接收 ...
Akka2使用探索1(Remoting) -
chenyehui:
这有点像nio, read和write的动作不需要user进程 ...
使用Akka的Actor和Future简单地实现并发处理 -
chenyehui:
hi 请问下 你这种方式 看不出来和Java 多线程的区别在哪 ...
使用Akka的Actor和Future简单地实现并发处理 -
henry_wu001:
这种调用是不是同步的,会不会阻塞?
Akka2使用探索5(Typed Actors) -
ZZX19880809:
啥ji巴玩意,copy也不看下,这啥样子了
Akka2使用探索7——“云计算”示例(Actor、Future、Remoting、Router、Deploy、异步、并发使用Demo)
基础数据类型,如String、Integer、Date、Boolean等它们可以很方便的映射到数据库:
import grails.persistence.Entity @Entity class MyEntity { String code String name static constraints = { code(unique: true, minSize: 4, maxSize: 4) name(blank: false, maxSize: 255) } }
这些基础数据类型是JAVA提供的语言级的,它没有语意。
比如要表达一个身份证号码:它有长度限制:15位或18位;还有规则限制;还能从身份证号码中提取出地址、性别、出生日期、年龄等信息。这些信息用一个String是无法表达,需要用类来描述:
class IDNumber{ String idNumber Address address InsDate birthday Gender gender IDNumber() {} IDNumber(val) { if (val.length() == 15) { val = to18IdNumber(val) } if (val.length() != 18) { throw new IllegalArgumentException("不是身份证格式") } this.idNumber = val return } def getAddress() { if (address) return address else return address = parseAddress() } def getBirthday() { if (birthday) return birthday else return birthday = parseBirth() } def getGender() { if (gender) return gender else return gender = parseGender() } def parseBirth() { ... } }
这个类里面最核心的就是String idNumber身份证号码,其他属性都是暂存的临时数据,可以从身份证号码里解析出来。如果想把这个类映射到数据库中,现在只能映射成一个table,但映射成table又不合理,最好是能映射成一列:
@grails.persistence.Entity
class PersonInfo {
String name
IDNumber idNumber
}
现在这样显然是不能达到这个目标的。
Hibernate提供了多种实现自定义类型的方法:
1、实现org.hibernate.usertype.UserType
2、实现org.hibernate.usertype.CompositeUserType
3、实现org.hibernate.usertype.UserCollectionType
4、实现org.hibernate.usertype.EnhanceUserType
通过实现这些接口,可以将自定义数据类型映射成数据库列。
UserType可以映射成单列,CompositeUserType可以映射成多列。
看个例子:
class MyString extends InsDataType implements UserType{ String value @Override void buildData(val) { if (val instanceof MyString) { value = val.value return } if (val == null) value = null else if (val instanceof String) value = val else if (val instanceof Number) value = String.valueOf(val) else value = val.toString() return } static MyString from(val) { if (val instanceof MyString) return val MyString data = new MyString() data.build(val) return data } public String toString() { return value } int[] sqlTypes() { return [Types.VARCHAR] } Class returnedClass() { return MyString } boolean equals(Object x, Object y) { MyString mx, my if (x instanceof String) mx = MyString.from(x) if (x instanceof MyString) mx = x if (y instanceof String) my = MyString.from(y) if (y instanceof MyString) my = y if (mx?.value == my?.value) return true return false } int hashCode(Object x) { return ((MyString) x)?.value?.hashCode() } Object nullSafeGet(ResultSet rs, String[] names, Object owner) { if (rs.wasNull()) return null // String stringFromDb = (String) Hibernate.STRING.nullSafeGet(rs, names[0]); String stringFromDb = rs.getString(names[0]); return MyString.from(stringFromDb) } void nullSafeSet(PreparedStatement st, Object value, int index) { if (value == null) st.setNull(index, Types.VARCHAR); else { MyString myString = (MyString) value; st.setString(index, myString.value); // Hibernate.STRING.nullSafeSet(st, myString.value, index); } } Object deepCopy(Object value) { if (!value || !((MyString) value).value) return null return MyString.from(value) } boolean isMutable() { return true } Serializable disassemble(Object value) { return ((MyString) value).value } Object assemble(Serializable cached, Object owner) { return MyString.from(cached) } Object replace(Object original, Object target, Object owner) { return null } }
这样就可以将MyString映射到数据库表中的一列了。
@grails.persistence.Entity class MyEntity { MyString name static constraints = { name(nullable: true) } static mapping = { name(length: 10) } }
数据库结构:
测试保存:
def testSave() { MyEntity entity = new MyEntity(name: MyString.from("hehe")) TestDomain.withTransaction { if (entity.hasErrors() || !entity.save(flush: true)) { println "save error:" + entity.errors } } }
数据库记录为:
测试查询:
MyEntity entity = MyEntity.findByName(MyString.from("hehe"))
现在操作自定义的MyString就像操作基础数据类型一样了。
如果一个数据类型有多个字段要存储,比如姓名分姓氏和名称。一种方法是把多个字段合并成一个字段,仍然使用UserType。另一种方法是用CompositeUserType。
class MyChineseName implements CompositeUserType { String familyName String givenName String[] getPropertyNames() { return ["familyName", "givenName"] as String[] } Type[] getPropertyTypes() { return [Hibernate.STRING, Hibernate.STRING] as Type[] } Object getPropertyValue(Object component, int property) { MyChineseName name = (MyChineseName) component; String result; switch (property) { case 0: result = name.familyName; break; case 1: result = name.givenName; break; default: throw new IllegalArgumentException("unknow property: " + property); } return result; } void setPropertyValue(Object component, int property, Object value) { MyChineseName name = (MyChineseName) component; String nameValue = (String) value; switch (property) { case 0: name.familyName = nameValue break; case 1: name.givenName = nameValue break; default: throw new IllegalArgumentException("unknow property: " + property); } } Class returnedClass() { return MyChineseName } boolean equals(Object x, Object y) { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); } int hashCode(Object x) { return x.hashCode() } Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) { if (rs.wasNull()) return null; String firstname = rs.getString(names[0]); String lastname = rs.getString(names[1]); return new MyChineseName(familyName: firstname, givenName: lastname); } void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session) { if (value == null) statement.setNull(index, Types.VARCHAR); else { MyChineseName name = (MyChineseName) value; // statement.setString(index, name.familyName); // statement.setString(index + 1, name.givenName); Hibernate.STRING.nullSafeSet(statement, name.familyName, index + 0); Hibernate.STRING.nullSafeSet(statement, name.givenName, index + 1); } } Object deepCopy(Object value) { if (value == null) return null; MyChineseName name = (MyChineseName) value; return new MyChineseName(familyName: name.familyName, givenName: name.givenName); } boolean isMutable() { return false } Serializable disassemble(Object value, SessionImplementor session) { return (Serializable) deepCopy(value); } Object assemble(Serializable cached, SessionImplementor session, Object owner) { return (Serializable) deepCopy(cached); } Object replace(Object original, Object target, SessionImplementor session, Object owner) { return null } }
这样,MyChineseName就能够映射成两列了。如果还像上面一样定义Entity类,Hibernate仍然无法映射,必须指定type和column:
@grails.persistence.Entity class MyEntity { MyChineseName name static constraints = { name(nullable: true) } static mapping = { name type: MyChineseName, { column name: "chineseFamilyName", length: 10 column name: "chineseGivenName", length: 10 } } }
生成的数据库表结构:
测试保存:
def testSave() { MyEntity entity = new MyEntity(name: new MyChineseName(familyName: "泛", givenName: "华")) TestDomain.withTransaction { if (entity.hasErrors() || !entity.save(flush: true)) { println "save error:" + entity.errors } } println ToStringBuilder.reflectionToString(entity) }
数据库记录为:
这种方式的麻烦之处在于映射时需要指定type和column。如果用户不清楚它的实现方式,仍然当作普通的UserType,没有指定type和column,那么就会报错:
Caused by: org.hibernate.MappingException: property mapping has wrong number of columns: com.baoxian.domain.MyEntity.name type: com.baoxian.datatype.MyChineseName
仅仅根据这个错误描述就不太好定位了。
可以把多字段组合成一个字符串,从而映射成一个字段来解决:
class MyChineseName implements UserType { String familyName String givenName String toOneString() { return "fn:${familyName};gn:${givenName}" } MyChineseName parseString(String str) { def regular = /(fn|gn):([^;]*)/ def result = str =~ regular def map = [:] result.each { map[it[1]] = it[2] } return new MyChineseName(familyName: map["fn"], givenName: map["gn"]) } int[] sqlTypes() { return [Types.VARCHAR] } Class returnedClass() { return MyChineseName } boolean equals(Object x, Object y) { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); } int hashCode(Object x) { return x.hashCode() } Object nullSafeGet(ResultSet rs, String[] names, Object owner) { return parseString(rs.getString(names[0])) } void nullSafeSet(PreparedStatement st, Object value, int index) { if (value == null) st.setNull(index, Types.VARCHAR); else { MyChineseName name = (MyChineseName) value st.setString(index, name.toOneString()) } } Object deepCopy(Object value) { if (value == null) return null; MyChineseName name = (MyChineseName) value; return new MyChineseName(familyName: name.familyName, givenName: name.givenName); } boolean isMutable() { return false } Serializable disassemble(Object value) { return (Serializable) deepCopy(value); } Object assemble(Serializable cached, Object owner) { return (Serializable) deepCopy(cached); } Object replace(Object original, Object target, Object owner) { return null } }
生成的数据库记录为:
除了实现CompositeUserType能将一个对象映射成多列,还有一种方法能达到这种效果:embedded。它能将本应映射成两个table的组合成一个表。
假设有两个实体关联如下:
@grails.persistence.Entity class MyComp { String name String code } @grails.persistence.Entity class MyEntity { String keyName MyComp comp static constraints = { comp(nullable: true) } }
这样,它会在数据库中映射成两个表,用ID关联起来。
因为关联表很简单,能不能组合成一张表呢?可以,用embedded:
class MyComp { String name String code } @grails.persistence.Entity class MyEntity { String keyName MyComp comp static embedded = ['comp'] static constraints = { comp(nullable: true) } }
生成的表为:
发表评论
-
Groovy元编程MOP(ExpandoMetaClass:EMC)的应用场景
2012-09-20 16:49 2546使用ExpandoMetaClass和Category可 ... -
用Groovy源编程(MOP)动态拦截(AOP)方法(比如记录String的concat和toUpperCase方法的耗费时间)
2012-09-10 17:36 2986实现AOP的方式有很多种,像Spring的AOP,它只能 ... -
序列化:Serializable和Externalizable
2012-08-29 15:25 953Externalizable是深度定制序列化。如果同时实 ... -
Akka2使用探索7——“云计算”示例(Actor、Future、Remoting、Router、Deploy、异步、并发使用Demo)
2012-08-22 15:39 1849假设有一个很耗时的运算,单台机器已经没法满足需求,这时你 ... -
Akka2使用探索6(Futures)——实现并发和异步
2012-08-14 18:01 4124Future用来获取某个并 ... -
Akka2使用探索5(Typed Actors)
2012-08-10 11:16 2351Akka 中的有类型 Actor 是 Active Ob ... -
Akka2使用探索3(Duration 和 Deadline)
2012-08-09 17:51 1391akka提供了两个关于时长的数据类型:Duration ... -
Akka2使用探索4(Actors)
2012-08-09 09:25 2190Actor模型为编写并发和分布式系统提供了一种更高的抽象 ... -
Akka2使用探索2(Configuration)
2012-08-09 09:21 1517akka2使用Typesafe Config库,可以 ... -
Akka2使用探索1(Remoting)
2012-08-09 09:20 7802akka从1.2升级到现在的2.0.2后有了很大的改变。 ... -
在父类获取子类属性
2010-06-29 11:53 2409在父类中能获取子类的属性吗?一般情况下是不行的,因为孩子尚未出 ... -
3D向量类
2009-11-11 13:50 1025隐藏行号 复制代码 ? 源代码 /* * ... -
3x3矩阵类
2009-11-11 16:03 10011: package com.jme.math; ...
相关推荐
然而,当数据库中存在特殊类型或者我们的业务逻辑需要特定的数据结构时,就需要自定义数据类型。 创建自定义数据类型主要包括以下几个步骤: 1. **定义映射类**:创建一个Java类,它将作为自定义数据类型的实现。...
而在Java持久化框架Hibernate中,这些数据类型需要与数据库中的字段类型进行映射,以便正确地存储和检索数据。这篇博客主要探讨了Java数据类型如何与Hibernate的类型映射进行对应。 首先,Java的基本数据类型在...
总结来说,`iBatis`的自定义数据类型机制允许我们在不支持中文的数据库中存储汉字,通过编写自定义的TypeHandler,我们可以灵活地将中文字符串转换为数据库可以接受的格式,然后在读取时恢复原状。这种方式在无法...
在本文中,我们将详细介绍如何使用用户自定义数据类型(UDT)和数据范围划定来规划标签数据库,并了解使用 UDT 的优势、如何优化 UDT 规划、使用数据范围划定来帮助简化并加快开发工作。 用户自定义数据类型(UDT)...
2. **实体属性定义**:为每个字段设置数据类型、长度等属性。 3. **关联关系**:定义不同表单之间的关联规则,支持主从表之间的数据引用。 #### 五、可视化的表单定制工具 1. **图形化界面**:提供易于使用的拖拽...
在AB PLC编程软件RSLOGIX5000中,用户自定义数据类型(UDT)是一种强大的工具,它允许工程师以更加逻辑和有序的方式组织控制系统的数据。UDT,也称为结构,允许将多种不同类型的数据(如整数、实数、定时器、布尔值等...
此外,Hibernate还支持自定义数据类型的映射,允许开发者根据需求扩展和定制。 在实际开发中,理解这些映射关系至关重要,因为它直接影响到数据的存储和查询效率,以及数据的一致性和完整性。例如,如果错误地将...
同时,Kettle支持自定义转换逻辑,可以应对各种复杂的数据清洗和转换需求,比如数据类型转换、缺失值处理、数据验证等。这种灵活性和强大的功能使得Kettle成为数据工程师在数据集成项目中的首选工具之一。
1. 数据转换:确保数据库表结构与Excel文件的列名和数据类型匹配,以便正确地映射和转换。 2. 异常处理:导入和导出过程中可能出现各种异常,如文件格式错误、数据库连接问题等,应合理处理这些异常,提供友好的错误...
在Java的Hibernate框架中,自定义类型是一种非常实用的功能,它允许开发者根据特定业务需求扩展Hibernate内置的数据类型。当我们发现Hibernate默认的数据类型无法满足我们存储数据的特殊要求时,例如需要处理复杂...
这个压缩包"Android高级应用源码-AndroidInject增加sqlite3数据库映射注解(ORM).zip"提供了一个示例,展示了如何在Android项目中使用SQLite3数据库,并通过ORM(对象关系映射)技术来简化数据库操作。ORM允许开发者...
在 Hibernate 框架中,使用自定义类型映射 Oracle 中的 LONG 类型字段是一种常见的解决方案。通过实现 UserType 接口,我们可以定制 LONG 类型字段的读写操作。在本例中,我们定义了一个名为 CustomLong 的类,该类...
难点为数据绑定,也就是页面元素与数据表字段的映射,另外动态数据存储结构问题、表间数据校验和计算、建立主从表的问题是难点。 五、表单加载、表单解析、表单数据处理和表单存储功能 除了可视化表单定制工具外,...
本资料包"安卓Andriod源码——Inject增加sqlite3数据库映射注解(ORM)"聚焦于如何通过注入(Inject)和对象关系映射(ORM)技术来简化SQLite3数据库的使用。 首先,我们需要理解ORM(Object-Relational Mapping)的...
例如,使用`DbContext`类作为数据库的上下文,定义实体类来映射数据库表,然后通过`DbSet<T>`属性进行数据操作。 在项目中,`efcore-master`可能是一个包含EF Core源码的仓库,开发者可以深入研究其内部实现,学习...
学习将对象映射到关系数据库的关键在于理解数据库与对象之间的关系,掌握如何定义映射,以及如何利用ORM框架进行数据操作。这份资料可能涵盖了这些基础知识,以及一些高级话题,如事务管理、性能优化等。通过深入...
在IT行业中,数据库管理和持久化框架是至关重要的组成部分,尤其是对于企业级应用开发。...在实际项目中,开发者可以根据需要自定义实体类的属性和方法,以及XML映射文件的配置,以满足复杂的业务需求。
在Java中,可以利用ORM(对象关系映射)框架如Hibernate,将自定义数据与数据库模型相结合,实现数据的持久化存储。 4. **在线设计**: 在线设计表单通常涉及Web界面,用户可以直接在浏览器中拖拽、编辑表单元素。...
本项目“AndroidInject增加sqlite3数据库映射注解(ORM)”是针对Android应用的一个源码示例,旨在教授如何通过对象关系映射(ORM)技术简化与SQLite3数据库的交互,提升开发效率,特别是在毕业设计或论文撰写过程中...
2. **自动数据类型转换**:框架内部处理了Java类型和数据库类型之间的转换,确保数据在对象与数据库间无缝流动。 3. **CRUD操作**:EasyDBO提供了简单易用的API,支持对数据库的创建(Create)、读取(Read)、更新...