Saturday 21 April 2012

1. EJB3 Annotation Types


Hibernate现在支持在嵌入式对象中使用关联注解(@*ToOne@*ToMany). EJB3规范尚不支持这样的用法。你可以使用 @AssociationOverride注解来覆写关联列.



参照Embeddable



l   所有没有定义注解的属性等价于在其上面添加了@Basic注解.
l   通过 @Basic注解可以声明属性的获取策略(fetch strategy)。但需要借助类增强器对二进制Class文件进行强化处理
@Basic(fetch=FetchType.LAZY)
private String info;
使用 @Column 注解可将属性映射到列. 使用该注解来覆盖默认值
@Column(name="reqdate")


定义了辨别符列(还可以定义辨别符的类型).
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
对于继承层次结构中的每个类,@DiscriminatorValue注解指定了用来辨别该类的值
@DiscriminatorValue("emp")
l   在实体中可以定义一个嵌入式组件(embedded component), 甚至覆盖该实体中原有的列映射.
l   组件类必须在类一级定义@Embeddable注解.
l   在特定的实体的关联属性上使用@Embedded @AttributeOverride注解可以覆盖该属性对应的嵌入式对象的列映射:

参照Embeddable

定义组合主键
@Id
@EmbeddedId
UserPK pk;
将一个类声明为一个实体bean(即一个持久化POJO)





默认是保存枚举的序列值, 但是你可以通过@Enumerated注解来进行调整
@Enumerated(EnumType.STRING)
private Gender gender;






使用 @GeneratedValue注解可以定义该标识符的生成策略:
AUTO - 可以是identity column类型,或者sequence类型或者table类型,取决于不同的底层数据库.
TABLE - 使用表保存id
IDENTITY - identity column
SEQUENCE - sequence

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
========================================
@javax.persistence.TableGenerator(
          name="MY_GEN",
          table="GENERATOR_TABLE",
          pkColumnName = "tablename",
          valueColumnName = "hi",
          pkColumnValue="dept",
          allocationSize=10
)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="MY_GEN")
int id;

声明了该实体bean的标识属性

定义组合主键,将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id
@IdClass(UserPK.class)
public class User {
继承映射。@Inheritance @DiscriminatorColumn 注解只能用于实体层次结构的顶端.
l   第一种(每个类一张表)
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Flight implements Serializable {
l   第二种(每个类层次结构一张表)
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="planetype",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue("Plane")
public class Plane { ... }
l   第三种(连接的子类)
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Boat implements Serializable { ... }

使用外键列进行实体的关联. 该注解和@Column注解有点类似, 但是多了一个名为referencedColumnName的参数。该参数定义了所关联目标实体中的联接列。注意,referencedColumnName关联到非主键列的时候, 关联的目标类必须实现Serializable, 还要注意的是所映射的属性对应单个列(否则映射无效).
@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@JoinColumn(name = "dp_id")
public Dept dept;


通过关联表
对于多对一也可以通过关联表的方式来映射。
       @ManyToOne(cascade={CascadeType.PERSIST})
      @JoinTable(name="deptuser",
            joinColumns=@JoinColumn(name="userid"),
            inverseJoinColumns=@JoinColumn(name="deptid")
      )
===============================================



@Lob注解表示属性将被持久化为Blob或者Clob类型, 具体取决于属性的类型, java.sql.Clob, Character[], char[] java.lang.String这些类型的属性都被持久化为Clob类型, java.sql.Blob, Byte[], byte[] serializable类型则被持久化为Blob类型.

你可以通过@ManyToMany注解可定义的多对多关联

在实体属性一级使用@ManyToOne注解来定义多对一关联:
@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
public Dept dept;
EJB3 允许你利用目标实体的一个属性作为Mapkey, 这个属性可以用@MapKey(name="myProperty")来声明.
@OneToMany(mappedBy = "dept", cascade = { CascadeType.ALL }, fetch =
        FetchType.LAZY)
@MapKey(name = "pk")
private Map<Integer, User> users = new HashMap<Integer, User>();
可以在嵌入式对象上添加 @MappedSuperclass注解, 这样可以将其父类的属性持久。
有时候通过一个(技术上或业务上)父类共享一些公共属性是很有用的, 同时还不用将该父类作为映射的实体(也就是该实体没有对应的表). 这个时候你需要使用@MappedSuperclass注解来进行映射.

映射本地化查询
@NamedNativeQueries(value = {
            @NamedNativeQuery(name="getlistall",
query="select * from user",
resultSetMapping="myMapping")
            ,@NamedNativeQuery(name="getlistone",
query="select * from user where id=1",
resultClass=com.bjsxt.hibernate.domain.User.class)
})
映射本地化查询

使用注解还可以映射EJBQL/HQL查询. @NamedQuery @NamedQueries是可使用在类和包上的注解.
@NamedQuery(name="getlistall",query="from User")
@NamedQueries(value = { @NamedQuery(name="getlistall",query="from User") })
@NamedQueries(value = {
            @NamedQuery(name="getlistall",query="from User")
            ,@NamedQuery(name="getlistone",query="from User where id = :id")
})

在属性级使用 @OneToMany注解可定义一对多关联

使用@OneToOne注解可以建立实体bean之间的一对一的关联.
一对一关联有三种情况: 一是关联的实体都共享同样的主键,
      @OneToOne
      @PrimaryKeyJoinColumn
      private Heart heart;
二是其中一个实体通过外键关联到另一个实体的主键 (注意要模拟一对一关联必须在外键列上添加唯一约束).
      @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="passport_fk")
      private Trousers trousers;
三是通过关联表来保存两个实体之间的连接关系 (注意要模拟一对一关联必须在每一个外键上添加唯一约束).
一对一关联可能是双向的.在双向关联中, 有且仅有一端是作为主体(owner)端存在的:主体端负责维护联接列(即更新). 对于不需要维护这种关系的从表则通过mappedBy属性进行声明. 如果在主体没有声明@JoinColumn,系统自动进行处理: 在主表(owner table)中将创建联接列, 列名为:主体的关联属性名+下划线+被关联端的主键列名.
对有序列表进行映射。该注解接受的参数格式:用逗号隔开的(目标实体)属性名及排序指令, firstname asc, age desc,如果该参数为空,则默认以id对该集合进行排序.

























l   当每个子类映射到一个表时, @PrimaryKeyJoinColumn @PrimaryKeyJoinColumns 注解定义了每个子类表关联到父类表的主键:
l   通过共享主键来进行一对一关联映射
      @OneToOne
      @PrimaryKeyJoinColumn
      private Heart heart;
===============================
@Entity
@PrimaryKeyJoinColumn(name="emp_id")
public class HourlyEmp extends Emp{
      int rate;



@javax.persistence.NamedQuery(name="findEmployeesInDept",
query="select emp from Employee emp where emp.department = ?1",
hints={@QueryHint(name="org.hibernate.cacheable",value="true")})
使用类一级的 @SecondaryTable @SecondaryTables 注解可以实现单个实体到多个表的映射.


定义了一个sequence 生成器,注意目前Hibernate Annotations还不支持sequence 生成器中的 initialValue allocationSize参数.

你还可以映射本地化查询(也就是普通SQL查询). 不过这需要你使用@SqlResultSetMapping注解来描述SQLresultset的结构
@SqlResultSetMapping(name="myMapping",entities={
            @EntityResult(entityClass=com.bjsxt.hibernate.domain.User.class,fields={
                  @FieldResult(name="id",column="id"),
                  @FieldResult(name="name",column="name"),
                  @FieldResult(name="info",column="info"),
                  @FieldResult(name="password",column="password"),
                  @FieldResult(name="username",column="username"),
                  @FieldResult(name="dept",column="dept_id"),
            })
})
如果你打算定义多个结果集映射,可是使用@SqlResultSetMappings

l   @Table是类一级的注解
l   通过@Table注解可以为实体bean映射指定表(table),目录(catalog)schema的名字.
l   如果没有定义@Table,那么系统自动使用默认值:实体的短类名(不附带包名).
@Entity
@Table(name="tbl_user")
标识符的生成策略的一种
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@javax.persistence.TableGenerator(
    name="EMP_GEN",
    table="GENERATOR_TABLE",
    pkColumnName = "tablename",
    valueColumnName = "hi",
    pkColumnValue="EMP",
    allocationSize=20
)
在核心的Java API中并没有定义时间精度(temporal precision). 因此处理时间类型数据时,你还需要定义将其存储在数据库中所预期的精度. 在数据库中,表示时间类型的数据有DATE, TIME, TIMESTAMP三种精度(即单纯的日期,时间,或者两者兼备). 可使用@Temporal注解来调整精度.
@Temporal(TemporalType.DATE)
@Column(name="reqdate")
private Date date;
实体bean中所有的非statictransient的属性都可以被持久化, 除非你将其注解为@Transient.
@Transient
private String info;

@Table结合使用@UniqueConstraint注解可以定义表的唯一约束(unique constraint) (对于绑定到单列的唯一约束,请参考@Column注解)

你可以在实体bean中使用@Version注解,通过这种方式可添加对乐观锁定的支持: 根据EJB3规范,version列可以是numeric类型(推荐方式)也可以是timestamp类型. Hibernate支持任何自定义类型,只要该类型实现了UserVersionType.

No comments:

Post a Comment