通过注解,你可以从代码中访问这个信息,但一个特别注解的属性不能像普通java对象的属性那样被直接引用。以下是一个示例:
这是使用注解访问元数据的方式:
Method field = Employee.class.getDeclaredMethod( "getFirstname", new Class[0] ); javax.persistence.Column col = field.getAnnotation( javax.persistence.Column.class ); int length = col.length();
这段代码与使用Empire-db的对象模型架构定义效果相同:
int length = mydb.EMPLOYEES.FIRSTNAME.getSize();
(注意EMPLOYEES和FIRSTNAME都是public final修饰的大写的成员变量,但也可以通过getter进行访问——具体访问方式取决于你的代码和决定)。
注解也有问题的原因不仅在于编译时安全的缺失与用户端代码的复杂性,它也有很多其他问题。持久化注解所提供的元数据通常并不充足。因此你需要像 Hibernate Validator 提供的附加的注解,或你可能想自定义注解,而这些会使你的映射与访问代码更加难以阅读和管理。更不用说在运行时改变你的数据模型是不可能的了。为元数据使用java对象模型要比以上这些方式都简单易行。既然不用注解可以做得更好那为什么还非要使用它呢?
除了元数据,我们也需要在某地存取我们自己的数据。对于Hibernate和JPA这个地方就是(装备了与相应表各字段对应的成员变量及它的getter setter方法的)JavaBean或POJO。对于大型数据模型这也就意味着很多行的代码。Hibernate工具可以通过逆向工程自动生成这些代码。但对于大型成熟的工程你可能会遇到这样的问题:一旦你手动更改了bean或映射代码——并且你希望保存这些改动——自动化工具就出问题了。所以通常这些代码(包括元数据)是通过手工维护的。更糟糕的是,因为这些对象通常用作填充业务对象的DTO(数据传送对象),你可能会看到用于Java对象间复制属性值的无数行代码。所以最好要把这些getter和setter放到哪里呢?
Empire-db的动态bean对于每个实现的实体都只有一个通用的getter和setter方法。我们仍推荐为每个数据库实体创建一个单独的数据对象类,这样类的总数没有变——虽然当使用一个通用DBRecord对象时这是没必要的, 但我们推荐这样做有两个原因:首先是为了类型安全,因为你希望你的代码依赖于特定的实体。其次,因为随着项目的增长,你很可能需要重写已经存在的方法并实现的新方法。尽管是这样,但因为少了这些成员变量和它们对应的getter setter方法,你会有相当少的代码需要维护。另外,如果有必要或为了简便,你可能要为某字段添加特殊的getter setter。
对于一个关系型数据库,我们希望它可以友好地支持动态查询,接下来我们看下Hibernate是如何处理动态查询的。 Hibernate提供两种方法: Hibernate查询语言(HQL)和标准的API。 HQL是Hibernate自己的语言,你必须先学习如何使用它。 它可以视为一个支持java编码映射的SQL方言。 当你尝试编译一个复杂的、带有约束和连接的、有条件查询语句时,就会发生问题,因为HQL是由不安全的字符串常量拼接成的。 我们认为在一些复杂度比较高的场景,使用HQL编写的代码会变得难以维护。 此时,标准的API是更好的选择,但是这种方法有缺点:灵活性比较低。
但这又出现了另一个问题:通常的编程任务是需要从一个或多个表中选出几个字段的集合或计算结果。查询结果可能用于展示给某一用户,或用于做其他处理。
对此Hibernate的HQL提供了可定义的select子句,原理是提供了一个特殊的结果bean,它持有你所需要的数据,甚至通过string拼接和数值运算这类SQL函数对其进行转换。但奇怪的这个功能在项目中几乎没有被用到过,人们转而使用全实体bean(full entity bean),这也就意味着从数据库中加载了很多没用的属性。对于实体间关系的解析,Hibernate既可以使用join(饿汉式)加载所有引用到的实体,也可以启用懒汉模式——查询每个引用到的对象——有时甚至只为了一个简单的属性。所以假设对于有5个属性的结果bean,实际上该对象不是持有5个属性,而是5个对象共加载了超过50个属性。很明显这不是你所期望的完美方案。
评论删除后,数据将无法恢复
评论(38)
引用来自“wangle85”的评论
Hibernate框架本身的复杂性有很多时候超过了业务本身引用来自“糖咖啡”的评论
用hibernate搞报表 完全崩溃。。。引用来自“zfc827”的评论
作者对Hibernate的理解和认识应该是多年前的眼光,Hibernate本身无疑是强大的,几乎没有人否认过,当然也存在着各种的不足。可是Java世界之所以这么健壮(也可以说是“复杂”),就是因为从来不缺乏解决方案。1、元数据的问题
传统的ORM架构设计,无非就是XML和注解的选择,基本上脱离不了这个,但是约定大于配置的理念出现后,Hibernate也有做了部分的改进,包括支持JPA注解,默认的字段关联,按照约定的方式使得代码中的注解数量大大减少。
2、泛滥的getter setter
这确实是一个Java中让人恶心和诟病的问题,但是硬要扯到Hibernate身上也很牵强,我现在使用Lombok,可以只写属性,所有的getter setter和基本的equals、hash、toString都在编译时动态生成好,源代码会看起来非常简洁。
引用来自“zfc827”的评论
3、查询的困境 其实我现在使用Hibernate仅仅只是作为JPA的实现了,代码中也没有用到Hibernate的HQL以及Criteria API,自从Spring Data JPA项目诞生后,将接口改为JPA的方式就成了顺理成章的事情,这些我想用过Spring Data JPA的同学都有体会。 另外,查询的问题我也赞同文中的观点,使用HQL,JPQL等等查询语句会让代码变的难以维护,更重要的是让代码变得不那么优雅。引用来自“zfc827”的评论
作者对Hibernate的理解和认识应该是多年前的眼光,Hibernate本身无疑是强大的,几乎没有人否认过,当然也存在着各种的不足。可是Java世界之所以这么健壮(也可以说是“复杂”),就是因为从来不缺乏解决方案。1、元数据的问题
传统的ORM架构设计,无非就是XML和注解的选择,基本上脱离不了这个,但是约定大于配置的理念出现后,Hibernate也有做了部分的改进,包括支持JPA注解,默认的字段关联,按照约定的方式使得代码中的注解数量大大减少。
2、泛滥的getter setter
这确实是一个Java中让人恶心和诟病的问题,但是硬要扯到Hibernate身上也很牵强,我现在使用Lombok,可以只写属性,所有的getter setter和基本的equals、hash、toString都在编译时动态生成好,源代码会看起来非常简洁。