2019独角兽企业重金招聘Python工程师标准>>>
在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式以后,发现使用annotation的方式可以更简介,所以这里就简单记录下通过annotation来配置各种映射关系,在hibernate4以后已经将annotation的jar包集成进来了,如果使用hibernate3的版本就需要引入annotation的jar包。
一、单对象操作
@Entity ---> 如果我们当前这个bean要设置成实体对象,就需要加上Entity这个注解
@Table(name="t_user") ----> 设置数据库的表名
public class User
{private int id;private String username;private String password;private Date born;private Date registerDate;
@Column(name="register_date") ---> Column中的name属性对应了数据库的该字段名字,里面还有其他属性,例如length,nullable等等public Date getRegisterDate(){return registerDate;}public void setRegisterDate(Date registerDate){this.registerDate = registerDate;}
@Id ---> 定义为数据库的主键ID (建议不要在属性上引入注解,因为属性是private的,如果引入注解会破坏其封装特性,所以建议在getter方法上加入注解)@GeneratedValue ----> ID的生成策略为自动生成 public int getId(){return id;}public void setId(int id){this.id = id;}............
}
最后只需要在hibernate.cfg.xml文件里面将该实体类加进去即可:
<!-- 基于annotation的配置 --><mapping class="com.xiaoluo.bean.User"/>
<!-- 基于hbm.xml配置文件 --><mapping resource="com/xiaoluo/bean/User.hbm.xml"/>
这样我们就可以写测试类来进行我们的CRUD操作了。
二、一对多的映射(one-to-many)
这里我们定义了两个实体类,一个是ClassRoom,一个是Student,这两者是一对多的关联关系。
ClassRoom类:
@Entity
@Table(name="t_classroom")
public class ClassRoom
{private int id;private String className;private Set<Student> students;public ClassRoom(){students = new HashSet<Student>();}public void addStudent(Student student){students.add(student);}@Id@GeneratedValuepublic int getId(){return id;}public void setId(int id){this.id = id;}public String getClassName(){return className;}public void setClassName(String className){this.className = className;}@OneToMany(mappedBy="room") ---> OneToMany指定了一对多的关系,mappedBy="room"指定了由多的那一方来维护关联关系,mappedBy指的是多的一方对1的这一方的依赖的属性,(注意:如果没有指定由谁来维护关联关系,则系统会给我们创建一张中间表)@LazyCollection(LazyCollectionOption.EXTRA) ---> LazyCollection属性设置成EXTRA指定了当如果查询数据的个数时候,只会发出一条 count(*)的语句,提高性能public Set<Student> getStudents(){return students;}public void setStudents(Set<Student> students){this.students = students;}}
Student类:
@Entity
@Table(name="t_student")
public class Student
{private int id;private String name;private int age;private ClassRoom room;@ManyToOne(fetch=FetchType.LAZY) ---> ManyToOne指定了多对一的关系,fetch=FetchType.LAZY属性表示在多的那一方通过延迟加载的方式加载对象(默认不是延迟加载)@JoinColumn(name="rid") ---> 通过 JoinColumn 的name属性指定了外键的名称 rid (注意:如果我们不通过JoinColum来指定外键的名称,系统会给我们声明一个名称)public ClassRoom getRoom(){return room;}public void setRoom(ClassRoom room){this.room = room;}@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;}public int getAge(){return age;}public void setAge(int age){this.age = age;}}
三、一对一映射(One-to-One)
一对一关系这里定义了一个Person对象以及一个IDCard对象
Person类:
@Entity
@Table(name="t_person")
public class Person
{private int id;private String name;private IDCard card;@OneToOne(mappedBy="person") ---> 指定了OneToOne的关联关系,mappedBy同样指定由对方来进行维护关联关系public IDCard getCard(){return card;}public void setCard(IDCard card){this.card = card;}@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;}}
IDCard类:
@Entity
@Table(name="t_id_card")
public class IDCard
{private int id;private String no;private Person person;@Id@GeneratedValuepublic int getId(){return id;}public void setId(int id){this.id = id;}public String getNo(){return no;}public void setNo(String no){this.no = no;}@OneToOne ---> OnetoOne指定了一对一的关联关系,一对一中随便指定一方来维护映射关系,这里选择IDCard来进行维护@JoinColumn(name="pid") ---> 指定外键的名字 pidpublic Person getPerson(){return person;}public void setPerson(Person person){this.person = person;}
}
注意:在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系。
四、Many-to-Many映射(多对多映射关系)
多对多这里通常有两种处理方式,一种是通过建立一张中间表,然后由任一一个多的一方来维护关联关系,另一种就是将多对多拆分成两个一对多的关联关系
1.通过中间表由任一一个多的一方来维护关联关系
Teacher类:
@Entity
@Table(name="t_teacher")
public class Teacher
{private int id;private String name;private Set<Course> courses;public Teacher(){courses = new HashSet<Course>();}public void addCourse(Course course){courses.add(course);}@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;}@ManyToMany(mappedBy="teachers") ---> 表示由Course那一方来进行维护public Set<Course> getCourses(){return courses;}public void setCourses(Set<Course> courses){this.courses = courses;}}
Course类:
@Entity
@Table(name="t_course")
public class Course
{private int id;private String name;private Set<Teacher> teachers;public Course(){teachers = new HashSet<Teacher>();}public void addTeacher(Teacher teacher){teachers.add(teacher);}@ManyToMany ---> ManyToMany指定多对多的关联关系@JoinTable(name="t_teacher_course", joinColumns={ @JoinColumn(name="cid")}, inverseJoinColumns={ @JoinColumn(name = "tid") }) ---> 因为多对多之间会通过一张中间表来维护两表直接的关系,所以通过 JoinTable 这个注解来声明,name就是指定了中间表的名字,JoinColumns是一个 @JoinColumn类型的数组,表示的是我这方在对方中的外键名称,我方是Course,所以在对方外键的名称就是 rid,inverseJoinColumns也是一个 @JoinColumn类型的数组,表示的是对方在我这放中的外键名称,对方是Teacher,所以在我方外键的名称就是 tid public Set<Teacher> getTeachers(){return teachers;}public void setTeachers(Set<Teacher> teachers){this.teachers = teachers;}@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;}}
2.将Many-to-Many拆分成两个One-to-Many的映射(Admin、Role、AdminRole)
Admin类:
@Entity
@Table(name="t_admin")
public class Admin
{private int id;private String name;private Set<AdminRole> ars;public Admin(){ars = new HashSet<AdminRole>();}public void add(AdminRole ar){ars.add(ar);}@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;}@OneToMany(mappedBy="admin") ---> OneToMany关联到了AdminRole这个类,由AdminRole这个类来维护多对一的关系,mappedBy="admin"@LazyCollection(LazyCollectionOption.EXTRA) public Set<AdminRole> getArs(){return ars;}public void setArs(Set<AdminRole> ars){this.ars = ars;}
}
Role类:
@Entity
@Table(name="t_role")
public class Role
{private int id;private String name;private Set<AdminRole> ars;public Role(){ars = new HashSet<AdminRole>();}public void add(AdminRole ar){ars.add(ar);}@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;}@OneToMany(mappedBy="role") ---> OneToMany指定了由AdminRole这个类来维护多对一的关联关系,mappedBy="role"@LazyCollection(LazyCollectionOption.EXTRA)public Set<AdminRole> getArs(){return ars;}public void setArs(Set<AdminRole> ars){this.ars = ars;}
}
AdminRole类:
@Entity
@Table(name="t_admin_role")
public class AdminRole
{private int id;private String name;private Admin admin;private Role role;@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;}@ManyToOne ---> ManyToOne关联到Admin@JoinColumn(name="aid") public Admin getAdmin(){return admin;}public void setAdmin(Admin admin){this.admin = admin;}@ManyToOne ---> @JoinColumn(name="rid")public Role getRole(){return role;}public void setRole(Role role){this.role = role;}
}
小技巧:通过hibernate来进行插入操作的时候,不管是一对多、一对一还是多对多,都只需要记住一点,在哪个实体类声明了外键,就由哪个类来维护关系,在保存数据时,总是先保存的是没有维护关联关系的那一方的数据,后保存维护了关联关系的那一方的数据,如:
Person p = new Person();p.setName("xiaoluo");session.save(p);IDCard card = new IDCard();card.setNo("1111111111");card.setPerson(p);session.save(card);
以上就是对hibernate annotation注解方式来配置映射关系的一些总结。