hibernate_注解
@Entity
Po首先有一个Entity注解。标识此类为一个实体类。
@Table
Table注解的name属性指向数据库的表名
@Entity
@Table(name=”user”)
public class User implements java.io.Serializable {
@UniqueConstraint
唯一约束,其内部也会创建一个索引。
@Table(uniqueConstraints={
@UniqueConstraint(name=”index_name”,columnNames=”name”),
@UniqueConstraint(name=”index_nameage”,columnNames={ “name”,”age”})
})
其中columnNames为表的字段值。
@Index
索引
@Table(indexes=
{
@Index(name=”index_name”,columnList=”name”,unique=true),
@Index(name=”index_nameage”,columnList=”name,age”)
}
)
name属性为索引名称,
columnList为字段名
unique属性默认为false,表示普通索引。为true表示唯一约束索引,就和上面@UniqueConstraint一样了。
@Column
@Column(name="name",length=20)
**public** String getName() \{
**return** name;
\}
name属性为表的字段名
Length属性为字段长度
nullable属性为false表示不能为空,默认为true
unique属性为true表示唯一约束,会自动为其创建一个索引,如果上面已通过@UniqueConstraint创建了索引,将覆盖上面的索引。默认为false
insertable属性为false表示不能插入此字段,默认为true
updatable属性为false表示不能修改此字段,默认为true
columnDefinition属性为片段,注解在解析的时候将直接把片段中的内容放到sql语句中。如控制double类型精度,可以这么写:长度为10,精度为2(小数点后保留两位),默认值为0.00
@Column(name=”height”,columnDefinition=”double(10,2) default ‘0.00’”)
public Double getHeight() {
return height;
}
@Id @GeneratedValue
@Id // 主键
@GeneratedValue(strategy=GenerationType.IDENTITY)// 自增长
@Column(name=”ID”,unique=true)
public Long getId() {
**return** id;
}
@Temporal
处理日期类型:
1、若只显示日期:即:yyyy-MM-dd
在属性的get方法设置:@Temporal(TemporalType.DATE)
2、显示日期与时间:即:yyyy-MM-dd hhss
在属性的get方法设置: @Temporal(TemporalType.TIMESTAMP)
3、只显示时间:即:hhss
在属性的get方法设置:@Temporal(TemporalType.TIME)
如:
@Temporal(TemporalType.DATE)
@Column(name=”birth_date”)
public Date getBirth() {
**return** birth;
}
@MappedSuperclass
实体类基类,和@Table一样,但是不需要指向某一个表,也不需要在配置文件中加上mapping。
@MappedSuperclass
public class BaseEntity implements Serializable{
private static final long serialVersionUID = 1L;
private Long id;
**private** String name;
**private** Integer age;
**private** Date birth;
父类如实现就可改为如下:
@Entity
@Table(name=”user”)
public class User extends BaseEntity {
**private** Double height;
@Transient
@Transient表示该属性并非一个到数据库表的字段的映射,即此成员变量和数据库没有关系,可以用来对其他成员变量进行处理加工。
@Transient
**private** List<String> lists = **new** ArrayList<String>();
@Lob
LOB 代表大对象数据,包括 BLOB 和 CLOB 两种类型,前者用于存储大块的二进制数据,如图片数据,视频数据等,而后者用于存储长文本数据,如论坛的帖子内容,产品的详细描述等。
即:BLOB类型是字节类型,映射为实体中的类型可为byte[]、Byte[]。CLOB类型是长字符串类型,映射为实体中的类型可为char[]、Character[]、String类型。
值得注意的是:在不同的数据库中,大对象对应的字段类型是不尽相同的,如 DB2 对应 BLOB/CLOB,MySql 对应 BLOB/LONGTEXT,SqlServer 对应 IMAGE/TEXT。需要指出的是,有些数据库的大对象类型可以象简单类型一样访问,如 MySql 的 LONGTEXT 的操作方式和 VARCHAR 类型一样。在一般情况下, LOB 类型数据的访问方式不同于其它简单类型的数据,我们经常会以流的方式操作 LOB 类型的数据。此外,LOB 类型数据的访问不是线程安全的,需要为其单独分配相应的数据库资源,并在操作完成后释放资源。
**private** String content;// 存放大内容
private byte[] image;// 存放图片
private Blob image2;// 存放图片
@Lob
@Column(name=”content”)// 不要指定长度,mysql中就是longtext类型,有4M大小
public String getContent() {
return content;
}
@Lob
@Column(name=”image”)
public byte[] getImage() {
return image;
}
@Lob
@Column(name=”image2”)
public Blob getImage2() {
return image2;
}
注:在使用@Lob注解的时候可能会报一个错:(ILjava/io/Reader;J)
是因为JDBC驱动版本太低,mysql-connector-java-5.0.8-bin.jar
更新为5.1以上的版本,如:mysql-connector-java-5.1.6-bin.jar
应用:
读取本地图片,保存到记录:
{
Transaction tx = session.beginTransaction();
User user = new User();
try {
File file = new File(“d://good.png”);
byte[] bytes = new byte[(int)file.length()];
FileInputStream inputStream = new FileInputStream(file);
inputStream.read(bytes);
inputStream.close();
// 保存byte[]
user.setImage(bytes);
// 保存blob
user.setImageBolb(Hibernate.getLobCreator(session).createBlob(bytes));
session.save(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
tx.commit();
}
查询记录,保存byte[]、blob到本地图片:
{
User user = (User)session.get(User.class, 1);// 取主键为1的记录
try {
FileOutputStream outputStream = new FileOutputStream(“e://test.png”);
// byte[]字段
byte [] bytes = user.getImage();
// blob字段
int nLength = (int) user.getImageBolb().length();
byte[] bytes = user.getImageBolb().getBytes(0, nLength);
outputStream.write(bytes);
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Basic
对于一些特殊的属性,比如长文本型text、字节流型blob型的数据,在加载Entity时,这些属性对应的数据量比较大,有时创建实体时如果也加载的话,可能严重造成资源的占用。要想解决这些问题,此时就需要设置实体属性的加载方式为惰性加载(LAZY)。
@Lob
@Basic(fetch=FetchType.LAZY)
@Column(name=”image”)
public byte[] getImage() {
return image;
}
Fetch默认为FetchType.EAGER
即立即加载数据。
LAZY为懒加载,即使用session.get后此字段为null,只有当用到此字段时才去获取真正的数据。
@CollectionTable
关联表内容。如:school表中有个外键userId,指向user表的主键。那么user表中就可以如下定义以获取其对应的学校。
表结构如下:
User表:
School表:
即:gary毕业自一中和武大,mini毕业自北大。
在User类中:
private List
// schooles中的类型为String
@ElementCollection(targetClass=String.class)
// @CollectionTable 的name为表名,@JoinColumn 中的name为 school表中的外键名, referencedColumnName为user表中的主键
@CollectionTable(name=”school”,joinColumns={ @JoinColumn(name=”userId”,nullable=false,referencedColumnName=”id”)})
// 映射到school表的schoolname字段
@Column(name=”schoolname”)
public List
return schooles;
}
public void setSchooles(List
this.schooles = schooles;
}
写测试用例如下:
List
for (User u : users) {
System.out.println(u.getId() + “===” + u.getName());
for (String school : u.getSchooles()){
System.out.println(“毕业学校:”+school);
}
}
可以发现,同样是:List
如果输出的时候不输出school,则输出如下:
少了两次查询,可见这种查询是懒加载的。
还没有评论,来说两句吧...