注解映射
基于配置文件的操作需要为每个类书写对应的配置文件,这样会导致我们的系统架构起来很笨重,注解的方式可以零配置生成表。
注解映射的基本原理
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加就等于没有某种标记好处简化xml的配置。核心是反射机制(把编译的类反编译过来),注解就是在运行是new对象。
写自己的注解标签并测试
新建一个部门类,注意类中不能用private修饰,此时的类要用关键字@interface,与接口是不同的,
类中的方法既是属性又是方法不需要写方法题,类中写了几个注解时就写几个,运行时赋值。
package com.hibernate.entity;
import java.lang.annotation.*;
@Documented//文档的注解java生成doc
@Retention(RetentionPolicy.RUNTIME)//类的生命周期
@Dept(deptName="",deptNum="")//自己写的注解
public @interface Dept {
public String deptName();
public String deptNum();
}
测试类
类中包含一个参数为Class类型的方法,通过该参数的getAnnotation()获取到注解对应的类,在主函数中调用该方法,传入的参数是测试类.class。
package com.hibernate.test;
import com.hibernate.entity.Dept;
@Dept(deptName="政研部",deptNum="001")
public class TestAnnotaction {
public static void print(Class<?> c){
Dept dept=c.getAnnotation(Dept.class);
if(dept!=null){
System.out.println(dept.deptName()+";"+dept.deptNum());
}
}
public static void main(String[] args) {
TestAnnotaction.print(TestAnnotaction.class);
}
}
JDK几个常用注解
@SuppressWarnings(“serial”):压制警告。
@Deprecated:使某个方法过期。
@Override:重写父类的方法。
Hibernate注解基础标签
@Entity:描述注解的实体对象,放置位置在类的头部放置。
@Table:描述注解生成的表,其中name属性是生成表的表名称(字符串类型)。放置位置也是在类的头部,可选注解配置标签。
@Id:描述生成表时字段为主键,放置位置都在类的属性的头部,或者属性生成的get方法头部,注意:放置到set方法头部出错。
@Column:标签主要描述普通列,放置位置都在类的属性的头部,或者属性生成的get方法头部,注意:放置到set方法头部出错。
@GeneratedValue(strategy=GenerationType.AUTO)标示数据库主见是否自增放置位置都在类的属性的头部,或者属性生成的get方法头部,注意:放置到set方法头部出错。AUTO自动匹配当前数据库主键的生成方式。
通过注解最终可以达到使用xml映射的效果,不用再次编写xml映射生成类,简化开发,提高效率,降低成本。
基于注解方式映射表
注解需要的jar包,hibernate3版本的官方源码包中没有需要下载,可以去我的资源进行下载。添加hibernate日志对应的jar包。
创建user类注意:注解都在javax.persistence包下
package com.hibernate.entity;
import javax.persistence.*;
@Entity
public class User implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
}
在链接文件中进行配置标签还是mapping,此时需要配置的class属性置为类名称。
<mapping class="com.hibernate.entity.User" />
测试类包含主函数,主函数中包含以下几个内容,注意此时获取链接的类与之前有所不同,是Configure的一个子类
AnnotationConfiguration cfg=new AnnotationConfiguration().configure();
SchemaExport ex=new SchemaExport(cfg);
ex.create(true, true);
运行后的sql语句
可以看到字段长度是数据库中默认的,想要控制长度在对应的属性头部加一下注解,其中length的值为int类型。
@Column(length=50)
再次运行可以看到字段的长度发生了变化。
多对一
主要用的标签
@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER):描述的是对应关系,中的fetch属性:是hibernate的抓取机制,默认是延迟加载(懒加载),和相当于xml配置中的lazy相反;cascade属性:相当于xml配置文件中的级联操作属性的配置。
@JoinColumn(name=”fk_s_g”):描述的是关联类的属性,其中name属性描述的是关联类的引用名称,其实质在表中会生成外键。
创建学生和班级的类
班级类:包含基本的属性以及对应的get、set方法,注解配置类和id。
package com.hibernate.entity;
import javax.persistence.*;
@Entity
public class Grade {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String gradeName;
}
学生类:包含基本的属性和班级的引用以及对应的get、set方法,注解配置类、id和关系。
package com.hibernate.entity;
import javax.persistence.*;
@Entity
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String stuName;
@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="fk_s_g")
private Grade grade;
}
把类加到配置文件中,前后次序不做要求。
<mapping class="com.hibernate.entity.Student" />
<mapping class="com.hibernate.entity.Grade" />
运行测试生成过程如下图:
添加、删除的功能不做测试,因为和配置方式的实现方法是一致的。
一对多
学生类及其映射文件不做修改,在班级类中添加一个泛型为学生的集合(集合必须new不然操作在运行时会报空指针),对应的set、get方法和关系的注解。
运用到的注解
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy=”grade”)mappedBy属性:在一对多映射的时候映射的时候多的一端在以的一端所属的属性是谁,映射所关联的外键。
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="grade")
private Set<Student> students=new HashSet<Student>();
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
注意在一对多映射,添加数据时,虽然发送sql看上去是将外键添加到数据库中,其实通过一端添加多的一端是添加不了的外键加不上,xml映射时可以,但注解的方式是不可以的。因此添加无法完成,查询与xml方式一致。