剑指架构师系列-Hibernate需要掌握的Annotation

1、一对多的关系配置

@Entity@Table(name = "t_order")public class Order {@Id@GeneratedValueprivate int id;private String name;    /*     * 该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,     * 而且这种关系是递归调用的。举个例子:Order 和OrderItem有级联关系,那么删除Order时将同时删除它所对     * 应的OrderItem对象。而如果OrderItem还和其他的对象之间有级联关系,那么这样的操作会一直递归执行下去。     *     * CascadeType.PERSIST(级联新建)  貌似只能在关联对象单独保存后才可以     * CascadeType.REMOVE(级联删除) 有级联的效果     * CascadeType.REFRESH(级联刷新)     * CascadeType.MERGE(级联更新)     * CascadeType.ALL(选择全部四项)     *     * 级联的意思是允许你进行某个级联操作,例如是级联删除时,进行级联新建是不允许的     *     * mappedBy 属性值是多方中定义的一方的变量名,形成双向关系时需要定义     */@OneToMany(cascade ={ CascadeType.ALL},fetch = FetchType.EAGER,mappedBy = "order",targetEntity = OrderItem.class)private Set<OrderItem> orderItems = new HashSet<OrderItem>();// 省略}
// 通过@Entity注解将一个类声明为一个实体bean// 通过 @Table注解可以为实体bean映射指定表,name属性表示实体所对应表的名称,如果没有// 定义 @Table,那么系统自动使用默认值:实体的类名(不带包名)@Entity@Table(name = "t_orderitem")public class OrderItem implements java.io.Serializable {private static final long serialVersionUID = 1L;// 用于标记属性的主键    // @Id    // 表示持久化属性所映射表中的字段,如果属性名与表中的字段名相同,则可以省略@Column注解,    // 另外有两种方式标记,一是放在属性前,另一种是放在getter方法前    // @Column(name = "EMPLOYEE_ID")    /*     * 表生成器。将当前主键的值单独保存到一个数据库表中,主键的值每次都是从指定的表中查询来获得,     * 这种生成主键的方式是很常用的。这种方法生成主键的策略可以适用于任何数据库,不必担心不同数     * 据库不兼容造成的问题。推荐这种方式管理主键,很方便,集中式管理表的主键,而且更换数据     * 库不会造成很大的问题。     *//*     @TableGenerator(         name="tab-store",        // 该表主键生成策略的名称,可以自定义,它被引用在@GeneratedValue中设置的"generator"值中         table="GENERATOR_TABLE", // 表生成策略所持久化的表名,就是管理其它表主键的表         pkColumnName = "G_KEY",  // 表生成器中的列名,用来存放其它表的主键键名,这个列名是与表中的字段对应的         pkColumnValue="EMPLOYEE_PK",  // 实体表所对应到生成器表中的主键名,可以自定义         // 表生成器中的列名,实体表主键的下一个值,假设EMPLOYEE表中的EMPLOYEE_ID最大为2,那么此时,生成器表中与实体表主键对应的键名值则为3         valueColumnName = "G_VALUE",         allocationSize=1         // 表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50     )    */    /*     * 定义主键生成策略,这里因为使用的是TableGenerator,所以,主键的生成策略为GenerationType.TABLE,     * 生成主键策略的名称则为前面定义的”tab-store”。     *     * strategy = GenerationType.AUTO或是strategy = GenerationType.SEQUENCE,采用SEQUENCE序列是因为Oracle数据中不支持identity自动增长,     * 要想使用它,还得在数据库中创建一个序列。     *     * 采用的是SQL Server作为数据库时,如果想使用AUTO或是IDENTITY生成策略,则一定要对主键加上identity标识,如identity(1,1)。     * 不过对于AUTO来说,是根据不同的数据库选择最合适的自增主键生成策略。如果使用MySQL,则主键要定义AUTO_INCREMENT。     * 如果是Oracle,则要创建Sequence来实现自增。     *     * */@Id//@Column(name = "id")//@TableGenerator(name = "tab-store", table = "GENERATOR_TABLE", pkColumnName = "G_KEY", pkColumnValue = "ORDERITEM_PK", valueColumnName = "G_VALUE", allocationSize = 1)//@GeneratedValue(strategy = GenerationType.TABLE, generator = "tab-store")@GeneratedValueprivate Integer id; private String name; /*   optional属性是定义该关联类是否必须存在,值为false时,关联类双方都必须存在,如果关系被维护端不存在,        查询的结果为null。值为true时,关系被维护端可以不存在,查询的结果仍然会返回关系维护端,在关系维护端         中指向关系被维护端的属性为null。optional属性的默认值是true。   optional属性实际上指定关联类与被关联 类的join查询关系,如optional=false时join查询关系为inner join,   optional=true 时join 查询关系为left join。 */@ManyToOne(cascade ={ CascadeType.ALL},optional = false,fetch=FetchType.LAZY,targetEntity=Order.class)@JoinColumn(name = "order_id")// 在关系被维护端需要建立外键列指向关系维护端的主键列private Order order;          // ManyToOne表示多个Employee对应与一个Department,dept_id字段加入Employee表中// 省略}

  

2、多对多的关系配置

@Entity@Table(name = "Teacher")public class Teacher implements java.io.Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValueprivate Integer id;@Column(name = "name", length = 100) // 对应数据库中表的列,最大长度是100private String name;// @ManyToMany注释表示Teacher是多对多关系的一端。/* * @JoinTable描述了多对多关系的数据表关系。 * name属性指定中间表名称, joinColumns定义中间表与Teacher表的外键关系。 * inverseJoinColumns属性定义了中间表与另外一端(Student)的外键关系。 */    @JoinTable(    name="teacher_student",    joinColumns = {@JoinColumn(name="teacher_id")},    inverseJoinColumns={@JoinColumn(name="student_id")}    )@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)private Set<Student> students = new HashSet<Student>();        // 省略}

  

@Entity@Table(name = "Student")public class Student implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValueprivate Integer id;@Column(name = "name")private String name;@Column(name = "age")private Integer age;// @ManyToMany注释表示Student是多对多关系的一边,mappedBy属性定义了Student为双向关系的维护端// 有且仅有一个实体指定mappedBy属性// 这个teachers属性会在数据库中生成对应的teachers_id字段@ManyToMany(cascade = CascadeType.ALL,mappedBy = "students")private Set<Teacher> teachers = new HashSet<Teacher>();// 省略}

  

3、Hibernate中继承关系的使用

Hibernate的继承映射包含了三种不同的策略:

  1. 每簇类使用一个表
  2. 每个子类一个表
  3. 每个具体内一个表(有限制)

JPA同样支持3种类型的继承形式:

1.Single Table Strategy ,单表策略,一张表包含基类与子类的所有数据,很多情况下都是采用这样的冗余设计,通过一个discriminator来区分
2.Table Per Class Strategy ,每个子类对应一张表,每张表都拥有基类的属性
3.Join Strategy ,仍然是每个子类对应一张表,但此表中不包含基类的属性,仅仅是此子类的扩展属性,共享基类的属性

(1)单表策略

// 采用单表策略,通过@DiscriminatorColumn确定了标志值的字段和类型// @DiscriminatorValue注释,当Animal类型的Entity存入数据库时,JPA将自动把animal的值赋给animalType字段@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name="animalType")@DiscriminatorValue("animal")public class Animal {private int id;private String name;@Id@GeneratedValuepublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}@Entity@DiscriminatorValue("cat")public class Cat extends Animal {private String catName;        // 省略}@Entity@DiscriminatorValue(value="dog")public class Dog extends Animal{private String dogName; // 省略}

 

(2)Table per Class

采用Table Per Class策略的话,每个子类都将单独建表,并且都独立拥有基类中的所有属性,互相之间不共享

 

@Entity@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public class Animal {private int id;private String name;@Id@GeneratedValue(strategy=GenerationType.TABLE)public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}@Entity@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public class Cat extends Animal {private String catName;public String getCatName() {return catName;}public void setCatName(String catName) {this.catName = catName;}}@Entity@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public class Dog extends Animal{private String dogName;public String getDogName() {return dogName;}public void setDogName(String dogName) {this.dogName = dogName;}}

  

(3)Join策略

每个子类同样独立建表,基类也独立建表,只不过所有的子类的表中只有扩展属性,他们共享基类的表

@Entity@Inheritance(strategy=InheritanceType.JOINED)public class Animal {private int id;private String name;@Id@GeneratedValuepublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}@Entity@PrimaryKeyJoinColumn(name="catId")public class Cat extends Animal {private String catName;public String getCatName() {return catName;}public void setCatName(String catName) {this.catName = catName;}}@Entity@PrimaryKeyJoinColumn(name="dogId")public class Dog extends Animal{private String dogName;public String getDogName() {return dogName;}public void setDogName(String dogName) {this.dogName = dogName;}}

  

参考文章:

 1、http://www.360doc.com/content/11/0906/22/1542811_146326974.shtml