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

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 (?, ?)
配置:
  1. <classname="User"table="USER"dynamic-insert="true"dynamic-update="true">

  1. @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)


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

配置:
  1. <classname="User"table="USER"dynamic-insert="true"dynamic-update="true"
  2. mutable="false">

  1. @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true,mutable=false)
  2. @org.hibernate.annotations.AccessType
  3. The annotation@org.hibernate.annotations.AccessType should be considered deprecatedforFIELD and PROPERTY access. It is still useful howeverifyou need to use a custom access type.


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


·实体数据库命名约定;
  1. packagecn.partner4java.shop.bean;
  2. importorg.hibernate.cfg.ImprovedNamingStrategy;
  3. /**
  4. * 使每个表前面加上"PA_"
  5. * @author partner4java
  6. *
  7. */
  8. publicclassPANamingStrategyextendsImprovedNamingStrategy {
  9. /**
  10. * 当没有声明显示的名称时调用
  11. */
  12. @Override
  13. publicString classToTableName(String className) {
  14. return"PA_"+super.classToTableName(className);
  15. }
  16. /**
  17. * 当声明了显示的名称时调用
  18. * Alter the table name given in the mapping document
  19. */
  20. @Override
  21. publicString tableName(String tableName) {
  22. return"PA_"+super.tableName(tableName);
  23. }
  24. }

  1. packagecn.partner4java.shop.service;
  2. importorg.hibernate.cfg.Configuration;
  3. importcn.partner4java.shop.bean.PANamingStrategy;
  4. publicclassBaseTest {
  5. publicstaticvoidmain(String[] args) {
  6. Configuration configuration =newConfiguration();
  7. configuration.setNamingStrategy(newPANamingStrategy());
  8. configuration.configure().buildSessionFactory();
  9. }
  10. }

配置:<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
声明此字段不被 映射到数据库中


指定注解位置:
  1. @AccessType(value="field")//@AccessType(value="property")

  1. publicclassTestBean1implementsSerializable {

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


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

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

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


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

  1. <property name=""update="false"insert="false"></property>

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

  1. <property name=""update="false"insert="false"generated="always"></property>


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

  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。


映射组件:
  1. @Embedded
  2. privateAddress homeAddress;

  1. @Embeddable
  2. publicclassAddressimplementsSerializable {
  3. privateString street;
  4. privateString city;

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值