hibernate 4 映射持久化类 | hibernate 实战(第二版) 第4章映射持久化类 | 笔记

来源:互联网 发布:删除Linux的引导启动项 编辑:程序博客网 时间:2024/06/05 10:33
hibernate 实战(第二版) 
第4章映射持久化类 

本章内容 
本章介绍基础的映射选项,阐述类和属性如何被映射到表和列。我们介绍和讨论如何处理数据库同一性和主键, 
以及各种其他元数据设置如何被 用来定制Hibernate加载和存储对象的方式。所有映射示例都以hibernate的 
原生XML格式完成,且并列使用JPA注解和XML描述符。我们还深入探讨细粒度领域模型的映射,以及如何映射 
属性和嵌入的组件。 


1细粒度的领域建模 

Hibernate的一个主要目标是支持细粒度的领域建模,过去我们把它分离出来作为富领域模型最重要的必要条件。 
这是我们使用POJO的一个原因,粗略的说,细粒度意味着类比表要多。 


2映射带有同一性的实体 

持久化使事情变得复杂起来。利用对象/关系持久化,持久化对象是数据库表的一个特定行的内存表示。连同Java同一性(内存位置) 
和对象等同性一起,你还要选择数据库同一性(在持久化数据库仓库中的位置)。 
1、如果对象在JVM中占据着相同的内存位置,他们就是同一的。这可以通过使用==操作符进行检查。这个概念称作对象同一性。 
2、如果对象有着相同的值,他们就是相等的,如equals方法定义的一样。不显示覆盖这个方法的类,继承了由Object定义的实现, 
他比较对象同一性。这个概念称作等同性。 
3、如果存储在一个关系数据库中的对象标识相同的行,或者他们共享相同的表和主键值,他们就是同一的。这个概念称作数据库同一性。 


试验证明在同一个EntityManager里面,同一个id的对象是 == 的,也是同一个对象。 


通常声明setId()方法为私有,并让hibernate生成和设置标示符值。 


生成器名称 JPA GenerationType 选项 描述 
Native AUTO Native同一性生成器挑选其他同一性生成器如identity、sequence或者hilo,取决于底层数据库的能力。使用这个生成器保证映射元数据可以移植到不同的数据库管理器 
Identity IDENTITY 这个生成器支持DB2、Mysql、MS SQL Server、Sybase和HypersonicSQL中的同一性列。返回的标示符类型为long、short或者int。 
Sequence SEQUENCE Sequence、 
Parameters 这个生成器在DB2、PostgreSQL、Oracle、SAPDB或者Mckoi中创建一个序列:或者使用InterBase中的一个生成器。返回的标示符类型为long、short或者int。如果创建序列的其他设置要被添加到DDL,就使用sequence选择给序列定义一个目标名称(默认是hibernate_sequence)和paramters 



3类映射选项 

Hibernate生成update语句,会更新所有的列。 
在有些情况下,例如包含几百列的一个遗留表,在该表中,即使最简单的操作的sql语句也很大,必须关闭这个启动时 
的sql生成,并切换到运行时生成的动态语句。当大量实体时,也会影响启动时间,因为hibernate必须为CURD提前生 
成所有SQL语句: 
区别就是: 
Hibernate: insert into USER (user_Name) values (?) 
Hibernate: insert into USER (user_Name, password) values (?, ?) 
配置: 
view plaincopy to clipboardprint?
  1. <class name="User" table="USER" dynamic-insert="true" dynamic-update="true">  

view plaincopy to clipboardprint?
  1. @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)  


使实体不可变: 
一个特定类的实例可以是不可变的。 
效果: 
没有sql打印,也没有报错,也就是忽略了更新操作 

配置: 
view plaincopy to clipboardprint?
  1. <class name="User" table="USER" dynamic-insert="true" dynamic-update="true"   
  2.         mutable="false">  

view plaincopy to clipboardprint?
  1. @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true,mutable=false)        
  2.   
  3.   
  4. @org.hibernate.annotations.AccessType  
  5. The annotation @org.hibernate.annotations.AccessType should be considered deprecated for FIELD and PROPERTY access. It is still useful however if you need to use a custom access type.  


用引号把SQL标示符括起来。 


·实体数据库命名约定; 
view plaincopy to clipboardprint?
  1. package cn.partner4java.shop.bean;  
  2.   
  3. import org.hibernate.cfg.ImprovedNamingStrategy;  
  4.   
  5. /** 
  6. * 使每个表前面加上"PA_" 
  7. * @author partner4java 
  8. * 
  9. */  
  10. public class PANamingStrategy extends ImprovedNamingStrategy {  
  11.       
  12.     /** 
  13.      * 当没有声明显示的名称时调用 
  14.      */  
  15.     @Override  
  16.     public String classToTableName(String className) {  
  17.         return "PA_"super.classToTableName(className);  
  18.     }  
  19.   
  20.     /** 
  21.      * 当声明了显示的名称时调用 
  22.      * Alter the table name given in the mapping document 
  23.      */  
  24.     @Override  
  25.     public String tableName(String tableName) {  
  26.         return "PA_"super.tableName(tableName);  
  27.     }  
  28.       
  29.       
  30. }  

view plaincopy to clipboardprint?
  1. package cn.partner4java.shop.service;  
  2.   
  3. import org.hibernate.cfg.Configuration;  
  4.   
  5. import cn.partner4java.shop.bean.PANamingStrategy;  
  6.   
  7. public class BaseTest {  
  8.     public static void main(String[] args) {  
  9.         Configuration configuration = new Configuration();  
  10.         configuration.setNamingStrategy(new PANamingStrategy());  
  11.         configuration.configure().buildSessionFactory();  
  12.     }  
  13. }  

配置:<class name="BankAccount"> 生成表明:pa_bank_account 

配置:<class name="BankAccount" table="BankAccount"> 生成表明:pa_bank_account (书中说的是错误的) 

配置:<class name="BankAccount" table="BANK_ACCOUNT"> 生成表明:pa_bank_account 




4细粒度的模型和映射 

但是最少包括not-null属性,因为还没有提交给数据库之前会报告空指针异常。(看看save源码都做了些什么) 


被注解的实体从强制的@Id注解的位置继承默认的访问策略。(如果@Id已经在字段中而不是获取方法上声明, 
那么所有其他的属性 映射注解也必须在字段中) 


@Transient 
声明此字段不被 映射到数据库中 


指定注解位置: 
view plaincopy to clipboardprint?
  1. @AccessType(value="field"//@AccessType(value="property")  

view plaincopy to clipboardprint?
  1. public class TestBean1 implements Serializable {  

会报的错误: 
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: cn.partner4java.jpa.bean.TestBean1 


关联属性: 
一些字段可以不存在于表中,而是关联的一些属性,比如关联显示每个一个货物的所有出价平均值: 
view plaincopy to clipboardprint?
  1. @Formula("slect AVG(b.AMOUNT) from BID b where b.ITEM_ID = ID ")  

view plaincopy to clipboardprint?
  1. <property name="" formula="slect AVG(b.AMOUNT) from BID b where b.ITEM_ID = ID "></property>  

那么这个字段也不会出现在插入和更改SQL中 


前面我们说过可以使一个实体不可变(mutable="false"),那么也可以使一个字段不可变,忽略变动: 
view plaincopy to clipboardprint?
  1. @Column(updatable=false,insertable=false)  

view plaincopy to clipboardprint?
  1. <property name="" update="false" insert="false"></property>  

在此基础上来实现:生成的默认属性: 
就是有一些字段,比如是利用触发器生成的,也就是不是我们这里完成的,是第三方触发完成,那么当你插入或者更新完之后,又想获得的对象包括这个触发值,那么可以:
view plaincopy to clipboardprint?
  1. @org.hibernate.annotations.Generated(GenerationTime.ALWAYS)//GenerationTime.INSERT等  

view plaincopy to clipboardprint?
  1. <property name="" update="false" insert="false" generated="always"></property>  


默认值(有两点是必须注意的,一个是必须是null,一个是会引起为null): 
view plaincopy to clipboardprint?
  1. <property name="">  
  2.     <column name="" default="1"></column>  
  3. </property>  

view plaincopy to clipboardprint?
  1. @Column(columnDefinition="INTEGER default '1'")      

private Integer age;//*注意这里必须给Integer,因为int类型是有默认值0的 (也就是插入对象的这个属性的值必须是null) 
(DLL: `age` int(11) default '1',) 
*你还必须开启动态的插入更新语句的生成(@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true),以便包括默认值的列不会出现在每个语句中, 
否则将插入的是null。 


映射组件: 
view plaincopy to clipboardprint?
  1. @Embedded  
  2. private Address homeAddress;  

view plaincopy to clipboardprint?
  1. @Embeddable  
  2. public class Address implements Serializable {  
  3.     private String street;  
  4.     private String city;  

这两个字段就会包含到homeAddress属性的类里面。 
xml: 
view plaincopy to clipboardprint?
  1. <component name="homeAddress" class="Address">  
  2.      <property name=""></property>  
  3. </component>    

原创粉丝点击