`

hibernate注解—详解

阅读更多

Hibernate注释大全收藏 

Java代码  收藏代码
  1. 声明实体Bean  
  2.   
  3. @Entity  
  4. public class Flight implements Serializable {  
  5.   Long id;  
  6.   @Id  
  7.   public Long getId() { return id; }  
  8.   public void setId(Long id) { this.id = id; }  
  9. }  
  10.   
  11. @Entity 注解将一个类声明为实体 Bean, @Id 注解声明了该实体Bean的标识属性。  
  12.   
  13. Hibernate 可以对类的属性或者方法进行注解。属性对应field类别,方法的 getXxx()对应property类别。  
  14.   
  15. 定义表  
  16.   
  17. 通过 @Table 为实体Bean指定对应数据库表,目录和schema的名字。  
  18.   
  19. @Entity  
  20. @Table(name="tbl_sky")  
  21. public class Sky implements Serializable {  
  22.   
  23. ...  
  24.   
  25. @Table 注解包含一个schema和一个catelog 属性,使用@UniqueConstraints 可以定义表的唯一约束。  
  26.   
  27. @Table(name="tbl_sky",  
  28.   uniqueConstraints = {@UniqueConstraint(columnNames={"month""day"})}  
  29. )  
  30.   
  31. 上述代码在  "month" 和 "day" 两个 field 上加上 unique constrainst.  
  32.   
  33. @Version 注解用于支持乐观锁版本控制。  
  34.   
  35. @Entity  
  36. public class Flight implements Serializable {  
  37.    ...  
  38.    @Version  
  39.    @Column(name="OPTLOCK")  
  40.    public Integer getVersion() { ... }  
  41. }  
  42.   
  43. version属性映射到 "OPTLOCK" 列,entity manager 使用这个字段来检测冲突。 一般可以用 数字 或者 timestamp 类型来支持 version.  
  44.   
  45. 实体Bean中所有非static 非 transient 属性都可以被持久化,除非用@Transient注解。  
  46.   
  47. 默认情况下,所有属性都用 @Basic 注解。  
  48.   
  49. public transient int counter; //transient property  
  50.   
  51. private String firstname; //persistent property  
  52. @Transient  
  53. String getLengthInMeter() { ... } //transient property  
  54. String getName() {... } // persistent property  
  55. @Basic  
  56. int getLength() { ... } // persistent property  
  57. @Basic(fetch = FetchType.LAZY)  
  58. String getDetailedComment() { ... } // persistent property  
  59. @Temporal(TemporalType.TIME)  
  60. java.util.Date getDepartureTime() { ... } // persistent property  
  61. @Enumerated(EnumType.STRING)  
  62. Starred getNote() { ... } //enum persisted as String in database  
  63.   
  64. 上述代码中 counter, lengthInMeter 属性将忽略不被持久化,而 firstname, name, length 被定义为可持久化和可获取的。   
  65.   
  66. @TemporalType.(DATE,TIME,TIMESTAMP) 分别Map java.sql.(Date, Time, Timestamp).  
  67.   
  68. @Lob 注解属性将被持久化为 Blog 或 Clob 类型。具体的java.sql.Clob, Character[], char[] 和 java.lang.String 将被持久化为 Clob 类型. java.sql.Blob, Byte[], byte[] 和 serializable type 将被持久化为 Blob 类型。  
  69.   
  70. @Lob  
  71. public String getFullText() {  
  72.    return fullText;  // clob type  
  73. }  
  74.   
  75.   
  76. @Lob  
  77. public byte[] getFullCode() {  
  78.   return fullCode;  // blog type  
  79. }  
  80.   
  81. @Column 注解将属性映射到列。  
  82.   
  83. @Entity  
  84. public class Flight implements Serializable {  
  85.    ...  
  86.    @Column(updatable = false, name = "flight_name", nullable = false, length=50)  
  87.    public String getName() { ... }  
  88.   
  89. 定义 name 属性映射到 flight_name column, not null, can't update, length equal 50  
  90.   
  91. @Column(  
  92.    name="columnName"; (1) 列名  
  93.    boolean unique() default false; (2)    是否在该列上设置唯一约束  
  94.    boolean nullable() default true; (3)   列可空?  
  95.    boolean insertable() default true; (4) 该列是否作为生成 insert语句的一个列  
  96.    boolean updatable() default true; (5)  该列是否作为生成 update语句的一个列  
  97.    String columnDefinition() default ""; (6)  默认值  
  98.    String table() default ""; (7)             定义对应的表(deault 是主表)  
  99.    int length() default 255; (8)              列长度  
  100.    int precision() default 0// decimal precision (9)  decimal精度  
  101.    int scale() default 0// decimal scale        (10)  decimal长度  
  102.   
  103. 嵌入式对象(又称组件)也就是别的对象定义的属性  
  104.   
  105. 组件类必须在类一级定义 @Embeddable 注解。在特定的实体关联属性上使用 @Embeddable 和 @AttributeOverride 注解可以覆盖该属性对应的嵌入式对象的列映射。  
  106.   
  107. @Entity  
  108. public class Person implements Serializable {  
  109.    // Persistent component using defaults  
  110.    Address homeAddress;  
  111.    @Embedded  
  112.    @AttributeOverrides( {  
  113.       @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),  
  114.       @AttributeOverride(name="name", column = @Column(name="bornCountryName") )  
  115.    } )  
  116.    Country bornIn;  
  117.    ...  
  118. }  
  119.   
  120. @Embeddable  
  121. public class Address implements Serializable {  
  122.    String city;  
  123.    Country nationality; //no overriding here  
  124. }  
  125.   
  126. @Embeddable  
  127. public class Country implements Serializable {  
  128.    private String iso2;  
  129.    @Column(name="countryName"private String name;  
  130.    public String getIso2() { return iso2; }  
  131.    public void setIso2(String iso2) { this.iso2 = iso2; }  
  132.    public String getName() { return name; }  
  133.    public void setName(String name) { this.name = name; }  
  134.    ...  
  135. }  
  136.   
  137. Person 类定义了 Address 和  Country 对象,具体两个类实现见上。  
  138.   
  139. 无注解属性默认值:  
  140.   
  141. • 属性为简单类型,则映射为 @Basic  
  142.   
  143. • 属性对应的类型定义了 @Embeddable 注解,则映射为 @Embedded  
  144.   
  145. • 属性对应的类型实现了Serializable,则属性被映射为@Basic并在一个列中保存该对象的serialized版本。  
  146.   
  147. • 属性的类型为 java.sql.Clob or java.sql.Blob, 则映射到 @Lob 对应的类型。  
  148.   
  149. 映射主键属性  
  150.   
  151. @Id 注解可将实体Bean中某个属性定义为主键,使用@GenerateValue注解可以定义该标识符的生成策略。  
  152.   
  153. • AUTO -  可以是 identity column, sequence 或者 table 类型,取决于不同底层的数据库  
  154. • TABLE - 使用table保存id值  
  155. • IDENTITY - identity column  
  156. • SEQUENCE - seque  
  157.   
  158. nce   
  159.   
  160. @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")  
  161. public Integer getId() { ... }  
  162.   
  163. @Id @GeneratedValue(strategy=GenerationType.IDENTITY)  
  164. public Long getId() { ... }  
  165.   
  166. AUTO 生成器,适用与可移值的应用,多个@Id可以共享同一个 identifier生成器,只要把generator属性设成相同的值就可以。通过@SequenceGenerator 和 @TableGenerator 可以配置不同的 identifier 生成器。   
  167.   
  168. <table-generator name="EMP_GEN"  
  169.      table="GENERATOR_TABLE"  
  170.      pk-column-name="key"  
  171.      value-column-name="hi"  
  172.      pk-column-value="EMP"  
  173.      allocation-size="20"/>  
  174. //and the annotation equivalent  
  175. @javax.persistence.TableGenerator(  
  176.      name="EMP_GEN",  
  177.      table="GENERATOR_TABLE",  
  178.      pkColumnName = "key",  
  179.      valueColumnName = "hi"  
  180.      pkColumnValue="EMP",  
  181.      allocationSize=20  
  182. )  
  183. <sequence-generator name="SEQ_GEN"  
  184.      sequence-name="my_sequence"  
  185.      allocation-size="20"/>  
  186. //and the annotation equivalent  
  187. @javax.persistence.SequenceGenerator(  
  188.      name="SEQ_GEN",  
  189.      sequenceName="my_sequence",  
  190.      allocationSize=20  
  191. )  
  192.   
  193. The next example shows the definition of a sequence generator in a class scope:  
  194.   
  195. @Entity  
  196. @javax.persistence.SequenceGenerator(  
  197.     name="SEQ_STORE",  
  198.     sequenceName="my_sequence"  
  199. )  
  200. public class Store implements Serializable {  
  201.    private Long id;  
  202.    @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")  
  203.    public Long getId() { return id; }  
  204. }  
  205.   
  206. Store类使用名为my_sequence的sequence,并且SEQ_STORE生成器对于其他类是不可见的。  
  207.   
  208. 通过下面语法,你可以定义组合键。  
  209.   
  210. • 将组件类注解为 @Embeddable, 并将组件的属性注解为 @Id  
  211. • 将组件的属性注解为 @EmbeddedId  
  212. • 将类注解为 @IdClass,并将该实体中所有主键的属性都注解为 @Id  
  213.   
  214. @Entity  
  215. @IdClass(FootballerPk.class)  
  216. public class Footballer {  
  217.   //part of the id key  
  218.   @Id public String getFirstname() {  
  219.     return firstname;  
  220.   }  
  221.   public void setFirstname(String firstname) {  
  222.      this.firstname = firstname;  
  223.   }  
  224.   //part of the id key  
  225.   @Id public String getLastname() {  
  226.     return lastname;  
  227.   }  
  228.   public void setLastname(String lastname) {  
  229.     this.lastname = lastname;  
  230.   }  
  231.   public String getClub() {  
  232.     return club;  
  233.   }  
  234.   public void setClub(String club) {  
  235.    this.club = club;  
  236.   }  
  237.   //appropriate equals() and hashCode() implementation  
  238. }  
  239.   
  240. @Embeddable  
  241. public class FootballerPk implements Serializable {  
  242.   //same name and type as in Footballer  
  243.   public String getFirstname() {  
  244.     return firstname;  
  245.   }  
  246.   public void setFirstname(String firstname) {  
  247.     this.firstname = firstname;  
  248.   }  
  249.   //same name and type as in Footballer  
  250.   public String getLastname() {  
  251.     return lastname;  
  252.   }  
  253.   public void setLastname(String lastname) {  
  254.    this.lastname = lastname;  
  255.   }  
  256.   //appropriate equals() and hashCode() implementation  
  257. }  
  258.   
  259. @Entity  
  260. @AssociationOverride( name="id.channel", joinColumns = @JoinColumn(name="chan_id") )  
  261. public class TvMagazin {  
  262.    @EmbeddedId public TvMagazinPk id;  
  263.    @Temporal(TemporalType.TIME) Date time;  
  264. }  
  265.   
  266.   
  267. @Embeddable  
  268. public class TvMagazinPk implements Serializable {  
  269.    @ManyToOne  
  270.    public Channel channel;  
  271.    public String name;  
  272.    @ManyToOne  
  273.    public Presenter presenter;  
  274. }  
  275.   
  276. 映射继承关系  
  277.   
  278. EJB支持3种类型的继承。  
  279.   
  280. • Table per Class Strategy: the <union-class> element in Hibernate 每个类一张表  
  281. • Single Table per Class Hierarchy Strategy: the <subclass> element in Hibernate 每个类层次结构一张表  
  282. • Joined Subclass Strategy: the <joined-subclass> element in Hibernate 连接的子类策略  
  283.   
  284. @Inheritance 注解来定义所选的之类策略。  
  285.   
  286. 每个类一张表  
  287.   
  288. @Entity  
  289. @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)  
  290. public class Flight implements Serializable {  
  291.   
  292. 有缺点,如多态查询或关联。Hibernate 使用 SQL Union 查询来实现这种策略。 这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个表间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。  
  293.   
  294. 每个类层次结构一张表  
  295.   
  296. @Entity  
  297. @Inheritance(strategy=InheritanceType.SINGLE_TABLE)  
  298. @DiscriminatorColumn(  
  299.     name="planetype",  
  300.     discriminatorType=DiscriminatorType.STRING  
  301. )  
  302. @DiscriminatorValue("Plane")  
  303. public class Plane { ... }  
  304.   
  305. @Entity  
  306. @DiscriminatorValue("A320")  
  307. public class A320 extends Plane { ... }  
  308.   
  309. 整个层次结构中的所有父类和子类属性都映射到同一个表中,他们的实例通过一个辨别符列(discriminator)来区分。  
  310.   
  311. Plane 是父类。@DiscriminatorColumn 注解定义了辨别符列。对于继承层次结构中的每个类, @DiscriminatorValue 注解指定了用来辨别该类的值。 辨别符列名字默认为 DTYPE,其默认值为实体名。其类型为DiscriminatorType.STRING。  
  312.   
  313. 连接的子类  
  314.   
  315. @Entity  
  316. @Inheritance(strategy=InheritanceType.JOINED)  
  317. public class Boat implements Serializable { ... }  
  318.   
  319.   
  320. @Entity  
  321. public class Ferry extends Boat { ... }  
  322.   
  323. @Entity  
  324. @PrimaryKeyJoinColumn(name="BOAT_ID")  
  325. public class AmericaCupClass extends Boat { ... }  
  326.   
  327. 以上所有实体使用 JOINED 策略 Ferry和Boat class使用同名的主键关联(eg: Boat.id = Ferry.id), AmericaCupClass 和 Boat 关联的条件为 Boat.id = AmericaCupClass.BOAT_ID.  
  328.   
  329. 从父类继承的属性  
  330.   
  331. @MappedSuperclass  
  332. public class BaseEntity {  
  333.   @Basic  
  334.   @Temporal(TemporalType.TIMESTAMP)  
  335.   public Date getLastUpdate() { ... }  
  336.   public String getLastUpdater() { ... }  
  337.   ...  
  338. }  
  339.   
  340.   
  341. @Entity class Order extends BaseEntity {  
  342.   @Id public Integer getId() { ... }  
  343.   ...  
  344. }  
  345.   
  346. 继承父类的一些属性,但不用父类作为映射实体,这时候需要 @MappedSuperclass 注解。 上述实体映射到数据库中的时候对应 Order 实体Bean, 其具有 id, lastUpdate, lastUpdater 三个属性。如果没有@MappedSuperclass 注解,则父类中属性忽略,这是 Order 实体 Bean 只有 id 一个属性。  
  347.   
  348. 映射实体Bean的关联关系  
  349.   
  350. 一对一  
  351.   
  352. 使用 @OneToOne 注解可以建立实体Bean之间的一对一关系。一对一关系有3种情况。  
  353.   
  354. • 关联的实体都共享同样的主键。  
  355.   
  356. @Entity  
  357. public class Body {  
  358.   @Id  
  359.   public Long getId() { return id; }  
  360.   @OneToOne(cascade = CascadeType.ALL)  
  361.   @PrimaryKeyJoinColumn  
  362.   public Heart getHeart() {  
  363.      return heart;  
  364.   }  
  365.   ...  
  366. }  
  367.   
  368. @Entity  
  369. public class Heart {  
  370.   @Id  
  371.   public Long getId() { ...}  
  372. }  
  373.   
  374. 通过@PrimaryKeyJoinColumn 注解定义了一对一的关联关系。  
  375.   
  376.   
  377. 多对一  
  378.   
  379. 使用 @ManyToOne 注解定义多对一关系。  
  380.   
  381. @Entity()  
  382. public class Flight implements Serializable {  
  383.   @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )  
  384.   @JoinColumn(name="COMP_ID")  
  385.   public Company getCompany() {  
  386.     return company;  
  387.   }  
  388.   ...  
  389. }  
  390.   
  391. 其中@JoinColumn 注解是可选的,关键字段默认值和一对一关联的情况相似。列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。本例中为company_id,因为关联的属性是company, Company的主键为 id.  
  392.   
  393. @ManyToOne 注解有个targetEntity属性,该参数定义了目标实体名。通常不需要定义,大部分情况为默认值。但下面这种情况则需要 targetEntity 定义(使用接口作为返回值,而不是常用的实体)。  
  394.   
  395. @Entity()  
  396. public class Flight implements Serializable {  
  397.    @ManyToOne(cascade=   {CascadeType.PERSIST,CascadeType.MERGE},targetEntity= CompanyImpl.class)  
  398.    @JoinColumn(name="COMP_ID")  
  399.    public Company getCompany() {  
  400.      return company;  
  401.    }  
  402.    ...  
  403. }  
  404.   
  405.   
  406. public interface Company {  
  407.    ...  
  408.   
  409. 多对一也可以通过关联表的方式来映射,通过 @JoinTable 注解可定义关联表。该关联表包含指回实体的外键(通过@JoinTable.joinColumns)以及指向目标实体表的外键(通过@JoinTable.inverseJoinColumns).  
  410.   
  411. @Entity()  
  412. public class Flight implements Serializable {  
  413.   
  414.    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )  
  415.    @JoinTable(name="Flight_Company",  
  416.        joinColumns = @JoinColumn(name="FLIGHT_ID"),  
  417.        inverseJoinColumns = @JoinColumn(name="COMP_ID")  
  418.    )  
  419.    public Company getCompany() {  
  420.        return company;  
  421.    }  
  422.    ...  
  423. }  
  424.   
  425. 集合类型  
  426.   
  427.   
  428.   
  429.  一对多  
  430.   
  431. @OneToMany 注解可定义一对多关联。一对多关联可以是双向的。  
  432.   
  433. 双向  
  434.   
  435. 规范中多对一端几乎总是双向关联中的主体(owner)端,而一对多的关联注解为 @OneToMany(mappedBy=)  
  436.   
  437. @Entity  
  438. public class Troop {  
  439.   @OneToMany(mappedBy="troop")  
  440.   public Set<Soldier> getSoldiers() {  
  441.   ...  
  442. }  
  443.   
  444.   
  445. @Entity  
  446. public class Soldier {  
  447.   @ManyToOne  
  448.   @JoinColumn(name="troop_fk")  
  449.   public Troop getTroop() {  
  450.   ...  
  451.   }  
  452.   
  453. Troop 通过troop属性和Soldier建立了一对多的双向关联。在 mappedBy 端不必也不能定义任何物理映射。  
  454.   
  455. 单向  
  456.   
  457. @Entity  
  458. public class Customer implements Serializable {  
  459.    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)  
  460.    @JoinColumn(name="CUST_ID")  
  461.    public Set<Ticket> getTickets() {  
  462.       ...  
  463.    }  
  464.   
  465. @Entity  
  466. public class Ticket implements Serializable {  
  467.    ... //no bidir  
  468. }  
  469.   
  470. 一般通过连接表来实现这种关联,可以通过@JoinColumn注解来描述这种单向关联关系。上例 Customer 通过 CUST_ID 列和 Ticket 建立了单向关联关系。  
  471.   
  472. 通过关联表来处理单向关联  
  473.   
  474. @Entity  
  475. public class Trainer {  
  476.   @OneToMany  
  477.   @JoinTable(  
  478.      name="TrainedMonkeys",  
  479.      joinColumns = @JoinColumn( name="trainer_id"),  
  480.      inverseJoinColumns = @JoinColumn( name="monkey_id")  
  481.   )  
  482.   public Set<Monkey> getTrainedMonkeys() {  
  483.      ...  
  484.   }  
  485.   
  486.   
  487. @Entity  
  488. public class Monkey {  
  489.   ... //no bidir  
  490. }  
  491.   
  492. 通过关联表来处理单向一对多关系是首选,这种关联通过 @JoinTable 注解来进行描述。上例子中 Trainer 通过TrainedMonkeys表和Monkey建立了单向关联关系。其中外键trainer_id关联到Trainer(joinColumns)而外键monkey_id关联到Monkey(inverseJoinColumns).  
  493.   
  494. 默认处理机制  
  495.   
  496. 通过连接表来建立单向一对多关联不需要描述任何物理映射,表名由一下3个部分组成,主表(owner table)表名 + 下划线 + 从表(the other side table)表名。指向主表的外键名:主表表名+下划线+主表主键列名 指向从表的外键定义为唯一约束,用来表示一对多的关联关系。  
  497.   
  498. @Entity  
  499. public class Trainer {  
  500.   @OneToMany  
  501.   public Set<Tiger> getTrainedTigers() {  
  502.   ...  
  503. }  
  504.   
  505.   
  506. @Entity  
  507. public class Tiger {  
  508.   ... //no bidir  
  509. }  
  510.   
  511. 上述例子中 Trainer 和 Tiger 通过 Trainer_Tiger 连接表建立单向关联关系。其中外键 trainer_id 关联到 Trainer表,而外键 trainedTigers_id 关联到 Tiger 表。  
  512.   
  513. 多对多  
  514.   
  515. 通过 @ManyToMany 注解定义多对多关系,同时通过 @JoinTable 注解描述关联表和关联条件。其中一端定义为 owner, 另一段定义为 inverse(对关联表进行更新操作,这段被忽略)。  
  516.   
  517. @Entity  
  518. public class Employer implements Serializable {  
  519.   @ManyToMany(  
  520.     targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,  
  521.     cascade={CascadeType.PERSIST, CascadeType.MERGE}  
  522.   )  
  523.   @JoinTable(  
  524.     name="EMPLOYER_EMPLOYEE",  
  525.     joinColumns=@JoinColumn(name="EMPER_ID"),  
  526.     inverseJoinColumns=@JoinColumn(name="EMPEE_ID")  
  527.   )  
  528.   public Collection getEmployees() {  
  529.     return employees;  
  530.   }  
  531.   ...  
  532. }  
  533.   
  534. @Entity  
  535. public class Employee implements Serializable {  
  536.   @ManyToMany(  
  537.     cascade = {CascadeType.PERSIST, CascadeType.MERGE},  
  538.     mappedBy = "employees",  
  539.     targetEntity = Employer.class  
  540.   )  
  541.   public Collection getEmployers() {  
  542.     return employers;  
  543.   }  
  544. }  
  545.   
  546. 默认值:  
  547.   
  548. 关联表名:主表表名 + 下划线 + 从表表名;关联表到主表的外键:主表表名 + 下划线 + 主表中主键列名;关联表到从表的外键名:主表中用于关联的属性名 + 下划线 + 从表的主键列名。  
  549.   
  550. 用 cascading 实现传播持久化(Transitive persistence)  
  551.   
  552. cascade 属性接受值为 CascadeType 数组,其类型如下:  
  553.   
  554. • CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed 如果一个实体是受管状态,或者当 persist() 函数被调用时,触发级联创建(create)操作。  
  555.   
  556.   
  557. • CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed 如果一个实体是受管状态,或者当 merge() 函数被调用时,触发级联合并(merge)操作。  
  558.   
  559.   
  560. • CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called 当 delete() 函数被调用时,触发级联删除(remove)操作。  
  561.   
  562.   
  563. • CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called  当 refresh() 函数被调用时,出发级联更新(refresh)操作。  
  564.   
  565.   
  566. • CascadeType.ALL: all of the above  以上全部  
  567.   
  568. 映射二级列表  
  569.   
  570. 使用类一级的 @SecondaryTable 和 @SecondaryTables 注解可以实现单个实体到多个表的映射。使用 @Column 或者 @JoinColumn 注解中的 table 参数可以指定某个列所属的特定表。  
  571.   
  572. @Entity  
  573. @Table(name="MainCat")  
  574. @SecondaryTables({  
  575.     @SecondaryTable(name="Cat1", pkJoinColumns={  
  576.            @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")}),  
  577.     @SecondaryTable(name="Cat2", uniqueConstraints={  
  578.            @UniqueConstraint(columnNames={"storyPart2"})})  
  579.  })  
  580. public class Cat implements Serializable {  
  581.   private Integer id;  
  582.   private String name;  
  583.   
  584.   private String storyPart1;  
  585.   private String storyPart2;  
  586.   @Id @GeneratedValue  
  587.   public Integer getId() {  
  588.     return id;  
  589.   }  
  590.   public String getName() {  
  591.     return name;  
  592.   }  
  593.   @Column(table="Cat1")  
  594.   public String getStoryPart1() {  
  595.     return storyPart1;  
  596.   }  
  597.   @Column(table="Cat2")  
  598.   public String getStoryPart2() {  
  599.     return storyPart2;  
  600.   }  
  601.   
  602. 上述例子中, name 保存在 MainCat 表中,storyPart1保存在 Cat1 表中,storyPart2 保存在 Cat2 表中。 Cat1 表通过外键 cat_id 和 MainCat 表关联, Cat2 表通过 id 列和 MainCat 表关联。对storyPart2 列还定义了唯一约束。  
  603.   
  604. 映射查询  
  605.   
  606. 使用注解可以映射 EJBQL/HQL 查询,@NamedQuery 和 @NamedQueries 是可以使用在类级别或者JPA的XML文件中的注解。  
  607.   
  608. <entity-mappings>  
  609.  <named-query name="plane.getAll">  
  610.   <query>select p from Plane p</query>  
  611.  </named-query>  
  612.  ...  
  613. </entity-mappings>  
  614. ...  
  615. @Entity  
  616. @NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date")  
  617. public class Night {  
  618.  ...  
  619. }  
  620. public class MyDao {  
  621.  doStuff() {  
  622.    Query q = s.getNamedQuery("night.moreRecentThan");  
  623.    q.setDate( "date", aMonthAgo );  
  624.    List results = q.list();  
  625.    ...  
  626.  }  
  627.  ...  
  628. }  
  629.   
  630. 可以通过定义 QueryHint 数组的 hints 属性为查询提供一些 hint 信息。下图是一些 Hibernate hints:  
  631.   
  632.   
  633.   
  634. 映射本地化查询  
  635.   
  636. 通过@SqlResultSetMapping 注解来描述 SQL 的 resultset 结构。如果定义多个结果集映射,则用 @SqlResultSetMappings。  
  637.   
  638. @NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "  
  639.      + " night.night_date, area.id aid, night.area_id, area.name "  
  640.      + "from Night night, Area area where night.area_id = area.id", resultSetMapping="joinMapping")  
  641.   
  642. @SqlResultSetMapping( name="joinMapping", entities={  
  643.   @EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = {  
  644.    @FieldResult(name="id", column="nid"),  
  645.    @FieldResult(name="duration", column="night_duration"),  
  646.    @FieldResult(name="date", column="night_date"),  
  647.    @FieldResult(name="area", column="area_id"),  
  648.    discriminatorColumn="disc"  
  649.   }),  
  650.     
  651.   @EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = {  
  652.    @FieldResult(name="id", column="aid"),  
  653.    @FieldResult(name="name", column="name")  
  654.   })  
  655.  }  
  656. )  
  657.   
  658. 上面的例子,名为“night&area”的查询和 "joinMapping"结果集映射对应,该映射返回两个实体,分别为 Night 和 Area, 其中每个属性都和一个列关联,列名通过查询获取。  
  659.   
  660. @Entity  
  661. @SqlResultSetMapping(name="implicit",   
  662.   entities=@EntityResult(  
  663.     entityClass=org.hibernate.test.annotations.@NamedNativeQuery(  
  664.       name="implicitSample", query="select * from SpaceShip",   
  665.       resultSetMapping="implicit")  
  666. public class SpaceShip {  
  667.  private String name;  
  668.  private String model;  
  669.  private double speed;  
  670.  @Id  
  671.  public String getName() {  
  672.   return name;  
  673.  }  
  674.  public void setName(String name) {  
  675.   this.name = name;  
  676.  }  
  677.  @Column(name="model_txt")  
  678.  public String getModel() {  
  679.   return model;  
  680.  }  
  681.  public void setModel(String model) {  
  682.   this.model = model;  
  683.  }  
  684.  public double getSpeed() {  
  685.   return speed;  
  686.  }  
  687.  public void setSpeed(double speed) {  
  688.   this.speed = speed;  
  689.  }  
  690. }  
  691.   
  692. 上例中 model1 属性绑定到 model_txt 列,如果和相关实体关联设计到组合主键,那么应该使用 @FieldResult 注解来定义每个外键列。@FieldResult的名字组成:定义这种关系的属性名字 + "." + 主键名或主键列或主键属性。  
  693.   
  694. @Entity  
  695. @SqlResultSetMapping(name="compositekey",  
  696.  entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class,  
  697.   fields = {  
  698.    @FieldResult(name="name", column = "name"),  
  699.    @FieldResult(name="model", column = "model"),  
  700.    @FieldResult(name="speed", column = "speed"),  
  701.    @FieldResult(name="captain.firstname", column = "firstn"),  
  702.    @FieldResult(name="captain.lastname", column = "lastn"),  
  703.    @FieldResult(name="dimensions.length", column = "length"),  
  704.    @FieldResult(name="dimensions.width", column = "width")  
  705.   }),  
  706.  columns = { @ColumnResult(name = "surface"),  
  707.    
  708. @ColumnResult(name = "volume") } )  
  709.  @NamedNativeQuery(name="compositekey",  
  710.  query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as resultSetMapping="compositekey")  
  711. })  
  712.   
  713. 如果查询返回的是单个实体,或者打算用系统默认的映射,这种情况下可以不使用 resultSetMapping,而使用resultClass属性,例如:  
  714.   
  715. @NamedNativeQuery(name="implicitSample", query="select * from SpaceShip",  
  716.                                             resultClass=SpaceShip.class)  
  717. public class SpaceShip {  
  718.   
  719. Hibernate 独有的注解扩展  
  720.   
  721. Hibernate 提供了与其自身特性想吻合的注解,org.hibernate.annotations package包含了这些注解。  
  722.   
  723. 实体  
  724.   
  725. org.hibernate.annotations.Entity 定义了  Hibernate 实体需要的信息。  
  726.   
  727. • mutable: whether this entity is mutable or not  此实体是否可变  
  728.   
  729.   
  730. • dynamicInsert: allow dynamic SQL for inserts   用动态SQL新增  
  731.   
  732.   
  733. • dynamicUpdate: allow dynamic SQL for updates   用动态SQL更新  
  734.   
  735.   
  736. • selectBeforeUpdate: Specifies that Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified.指明Hibernate从不运行SQL Update,除非能确定对象已经被修改  
  737.   
  738.   
  739. • polymorphism: whether the entity polymorphism is of PolymorphismType.IMPLICIT (default) or PolymorphismType.EXPLICIT 指出实体多态是 PolymorphismType.IMPLICIT(默认)还是PolymorphismType.EXPLICIT   
  740.   
  741.   
  742. • optimisticLock: optimistic locking strategy (OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY or OptimisticLockType.ALL) 乐观锁策略  
  743.   
  744. 标识符  
  745.   
  746. @org.hibernate.annotations.GenericGenerator和@org.hibernate.annotations.GenericGenerators允许你定义hibernate特有的标识符。  
  747.   
  748. @Id @GeneratedValue(generator="system-uuid")  
  749. @GenericGenerator(name="system-uuid", strategy = "uuid")  
  750. public String getId() {  
  751. @Id @GeneratedValue(generator="hibseq")  
  752. @GenericGenerator(name="hibseq", strategy = "seqhilo",  
  753.    parameters = {  
  754.      @Parameter(name="max_lo", value = "5"),  
  755.      @Parameter(name="sequence", value="heybabyhey")  
  756.    }  
  757. )  
  758. public Integer getId() {  
  759.   
  760. 新例子  
  761.   
  762. @GenericGenerators(  
  763.  {  
  764.   @GenericGenerator(  
  765.    name="hibseq",  
  766.    strategy = "seqhilo",  
  767.    parameters = {  
  768.     @Parameter(name="max_lo", value = "5"),  
  769.     @Parameter(name="sequence", value="heybabyhey")  
  770.    }  
  771.   ),  
  772.   @GenericGenerator(...)  
  773.  }  
  774. )  
  775.   
  776. 自然ID  
  777.   
  778. 用 @NaturalId 注解标识  
  779.   
  780. 公式  
  781.   
  782. 让数据库而不是JVM进行计算。  
  783.   
  784. @Formula("obj_length * obj_height * obj_width")  
  785. public long getObjectVolume()  
  786.   
  787. 索引  
  788.   
  789. 通过在列属性(property)上使用@Index注解,可以指定特定列的索引,columnNames属性(attribute)将随之被忽略。  
  790.   
  791. @Column(secondaryTable="Cat1")  
  792. @Index(name="story1index")  
  793. public String getStoryPart1() {  
  794.   return storyPart1;  
  795. }  
  796.   
  797. 辨别符  
  798.   
  799. @Entity  
  800. @DiscriminatorFormula("case when forest_type is null then 0 else forest_type end")  
  801. public class Forest { ... }  
  802.   
  803. 过滤 查询 ...  
  804.   
  805.   
  806.   
  807.   
  808.   
  809. • 其中一个实体通过外键关联到另一个实体的主键。注:一对一,则外键必须为唯一约束。  
  810.   
  811. @Entity  
  812. public class Customer implements Serializable {  
  813.    @OneToOne(cascade = CascadeType.ALL)  
  814.    @JoinColumn(name="passport_fk")  
  815.    public Passport getPassport() {  
  816.    ...  
  817. }  
  818.   
  819.   
  820. @Entity  
  821. public class Passport implements Serializable {  
  822.    @OneToOne(mappedBy = "passport")  
  823.    public Customer getOwner() {  
  824.    ...  
  825. }  
  826.   
  827. 通过@JoinColumn注解定义一对一的关联关系。如果没有@JoinColumn注解,则系统自动处理,在主表中将创建连接列,列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。上例为 passport_id, 因为Customer 中关联属性为 passport, Passport 的主键为 id.  
  828.   
  829.   
  830. • 通过关联表来保存两个实体之间的关联关系。注:一对一,则关联表每个外键都必须是唯一约束。  
  831.   
  832. @Entity  
  833. public class Customer implements Serializable {  
  834.    @OneToOne(cascade = CascadeType.ALL)  
  835.    @JoinTable(name = "CustomerPassports",  
  836.         joinColumns = @JoinColumn(name="customer_fk"),  
  837.         inverseJoinColumns = @JoinColumn(name="passport_fk")  
  838.    )  
  839.    public Passport getPassport() {  
  840.    ...  
  841. }  
  842.   
  843.   
  844. @Entity public class Passport implements Serializable {  
  845.    @OneToOne(mappedBy = "passport")  
  846.    public Customer getOwner() {  
  847.    ...  
  848. }  
  849.   
  850. Customer 通过 CustomerPassports 关联表和 Passport 关联。该关联表通过 passport_fk 外键指向 Passport 表,该信心定义为 inverseJoinColumns 的属性值。 通过 customer_fk 外键指向 Customer 表,该信息定义为 joinColumns 属性值。 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics