在JDK 5.0之后出现了一种新的注释技术Annotations,而Hibernate也在其3.0之后的版本中添加了对Annotations的支持。通过在实体类中添加Annotations注释,可以达到替代映射文件的效果。
各Annotations注释标记如下:
@Entity 声明当前是一个持久化类
@Table 设置当前持久化类所映射的数据库表,如果当前类中没有使用@Table注解,Hibernate会自动使用默认的持久化类的类名(不带包名)作为所映射的表名
@Id 设置当前持久化类的标示符属性
@GeneratedValue 设置当前标示符的生产策略。@GeneratedValue的name属性设置生成策略的名称是TABLE、INENTITY、SEQUENCE或者AUTO之一。
@Column 将持久化类的数学与数据库表中的字段进行映射,name属性值为映射的字段名,length属性值为字段的长度,unique属性表示该列上设置唯一的约束,nullable属性设置该列的值是否可以为空,precision实现设置该字段的精度,scale属性设置该字段的小数位数
@Transient 标注的属性进行持久化映射
@Temporal java中没有定义时间精度的api,因此处理时间类型数据时,需要设置存储在数据库中所预期的精度,使用@Temporal注释可以调整时间的精度为:DATE、TIME和TIMESTAMP三种
@ManyToOne 设置该当前持久化类类与其他持久化类之间的多对一关联,其中CascadeType值表示Hibernate将进行级联操作
@OneToMany 设置该当前持久化类与其他持久化类之间的一对多关联
@OneToOne 设置该当前持久化类与其他持久化类之间的一对一关联
@ManyToMany 设置该当前持久化类与其他持久化类之间的多对多关联
@NameQueries 在持久化类中设置命名查询,参考@NameQuery的使用
@NameQuery 在持久化类中设置命名查询,@NamedQuery 和@NamedQueries注释加在在类和包上。如下面的例子:
@NamedQueries({@NamedQuery(name="queryById",query="select p from Product p where id=:id")})
@Version 设置乐观锁定
@Cache 设置二级缓存
@Filters 设置使用过滤器
@FilterDef 声明过滤器
举例如下:首先创建两个表
表CATEGORY
-- Create table
create table CATEGORY
(
ID NUMBER(8) not null,
NAME NVARCHAR2(200),
DESCRIPTION VARCHAR2(1000)
)
tablespace USERS
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
-- Create/Recreate primary, unique and foreign key constraints
alter table CATEGORY
add constraint CATEGORY_PK primary key (ID)
using index
tablespace USERS
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
表PRODUCT
-- Create table
create table PRODUCT
(
ID NUMBER(8) not null,
NAME VARCHAR2(200),
PRICE NUMBER(6,2),
DESCRIPTION VARCHAR2(1000),
CREATE_TIME DATE,
CATEGORY_ID NUMBER(8)
)
tablespace USERS
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
-- Create/Recreate primary, unique and foreign key constraints
alter table PRODUCT
add constraint PRODUCT_PK primary key (ID)
using index
tablespace USERS
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
alter table PRODUCT
add constraint PRODUCT_FK foreign key (CATEGORY_ID)
references CATEGORY (ID);
Category.java
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "CATEGORY", schema = "SCOTT")
public class Category implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String description;
private Set<Product> products = new HashSet<Product>(0);
public Category() {
}
// Property accessors
@GenericGenerator(name = "generator", strategy = "increment")
@Id
@GeneratedValue(generator = "generator")
@Column(name = "ID", unique = true, nullable = false, precision = 8, scale = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "NAME", length = 400)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "DESCRIPTION", length = 1000)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
public Set<Product> getProducts() {
return this.products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
}
product.java
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "PRODUCT", schema = "SCOTT")
public class Product implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Category category;
private String name;
private Double price;
private String description;
private Date createTime;
public Product() {
}
@GenericGenerator(name = "generator", strategy = "increment")
@Id
@GeneratedValue(generator = "generator")
@Column(name = "ID", unique = true, nullable = false, precision = 8, scale = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CATEGORY_ID")
public Category getCategory() {
return this.category;
}
public void setCategory(Category category) {
this.category = category;
}
@Column(name = "NAME", length = 200)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "PRICE", precision = 6)
public Double getPrice() {
return this.price;
}
public void setPrice(Double price) {
this.price = price;
}
@Column(name = "DESCRIPTION", length = 1000)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
@Temporal(TemporalType.DATE)
@Column(name = "CREATE_TIME", length = 7)
public Date getCreateTime() {
return this.createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateAnnotationsTest {
public void testAnnotations() {
SessionFactory sessionFactory = new AnnotationConfiguration().configure()
.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Category category = new Category();
category.setName("demo");
category.setDescription("这是一个例子");
Product product = new Product();
product.setName("妮维雅");
product.setPrice(new Double(46.0));
product.setDescription("护肤品");
product.setCategory(category);
category.getProducts().add(product);
Transaction tx = session.beginTransaction();
session.save(category);
session.save(product);
tx.commit();
sessionFactory.close();
}
public static void main(String[] args) {
HibernateAnnotationsTest test = new HibernateAnnotationsTest();
test.testAnnotations();
}
}
@GeneratedValue注解生成策略
TABLE 借助数据库表,生成存标识符属性值,表中保存当前的标识符属性的最大值
IDENTITY 使用数据库表中的自动增长字段生成标识符属性值
SEQUENCE 使用数据库的序列生成标识符属性值
AUTO 可以是上面三种任意一种类型,取决于底层数据库的类型
hibrenate @ManyToOne(fetch = FetchType.EAGER) 和 lazy 区别
如果是LAZY,那么取出这条数据时,它关联的数据并不取出来,在同一个session中,什么时候要用,就什么时候取(再次访问数据库)。
但是,在session外,就不能再取了。用EAGER时,因为在内存里,所以在session外也可以取。
一般只在一边设Eager,JPA接口默认为一对多为Lazy,多对一为Eager,但是Hibernate反向工程生成Entity时,多对一为Lazy,需要手动改为Eager。
而两边都设Eager,那么代码中取一条记录时,会发2次SQL。