Hibernate实体关系映射—Annotation

Hibernate实体关系映射分为:

    单边一对一,双边一对一;

    单边一对多,单边多对一;

    双边一对多,双边多对一;

    单边多对多,双边多对多;

    以及主键相同的单双边一对一。下面分别总结这几种关系映射的注解方法:

1.  单边一对一和双边一对一

    单边一对一:比如一个学生(Student)有一个学生证(StudentCard),且Student类中有一个StudentCard对象:

@Entity  
@Table(name = "student")  
public class Student {  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)   
    private String id;  
   
    private String name;  
   
    @OneToOne(cascade = {CascadeType.ALL})  
    @JoinColumn(name = "student_id", unique = true)  
    private StudentCard stuCard;  
   
    //省略set,get方法,注解本应该放在get方法上,这里为了方便,放在成员变量上了。  
}  
   
@Entity  
@Table(name = "studentid")  
public class StudentCard {  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)   
    private String id;  
   
    private int num;  
} 
    @Table中name属性表示指定实体对应 的表名,可以不指定。   

    @GeneratedValue表示主键自增长类型,有AUTO, TABLE, SEQUENCE, IDENTITY四种方式:

        GenerationType.AUTO:自动方式,根据底层数据库自动选择;

        GenerationType.TABLE:使用指定的表来决定主键的取值,一般结合@TableGenerator使用;

        GenerationType.SEQUECE:使用Sequece来决定主键的取值,适合Oracle、DB2、PostgreSQL、SAP DB等支持Sequence的数据库,一般结合@SequenceGnerator使用;

        GenerationType.IDENTITY:支持DB2、MySQL、MS SQL Server、Sybase与HypersonicSQL数据库的identity类型主键。

    @OneToOne表示一对一,cascade配置级联方式,有PERSIST、REMOVE、MERGE、REFRESH等几种取值,分别表示在保存、删除、修改、刷新Student类时,会自动在数据库    

    中保存、删除、修改、刷新属于它的StudentCard对象,ALL则表示所有动作皆级联。即级联后可以通过操作Student类来操作StudentCard类。

    双边一对一:比如丈夫(Husband)和妻子(Wife),每个类中皆有对方的类对象:
    @Entity  
    public class Husband {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        private String name;  
       
        @OneToOne  
        @JoinColumn(name="wifeId")//wifeId作为外键字段,关联wife表中的主键  
        private Wife wife;  
    }  
       
    @Entity  
    public class Wife {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        private String name;  
       
        @OneToOne(mappedBy = "wife")//表示已经在Husband类中对wife做了映射了。一般有双向关联的都要设置mappedBy   
        private Husband husband;  
    }  

2. 单边一对多和单边多对一

    单边一对多:比如一个组(Group)里有多个用户(User),Group类中有存储User的集合:

    @Entity  
    @Table(name="t_group")//group在sql中是关键词,避免冲突  
    public class Group {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        private String name;  
       
        @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)  
        @JoinColumn(name="groupid")//表示t_user表中有个叫group_id的外键字段  
        private Set<User> users = new HashSet<User>();  
    }  
       
    @Entity  
    @Table(name="t_user")  
    public class User {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)   
        private int id;  
       
        private String name;  
    }  
    fetch属性有两个值:EAGER和LAZY。分别表示即时加载和延迟加载,这是ORM框架引入的概念。

        fetch = FetchType.LAZY表示加载group时不加载user,一般一对多的时候,在一方默认为LAZY,因为如果多方数据太多,会导致大量数据的加载,影响性能  

    单边多对一:比如一个组(Group)里有多个用户(User),User类中有Group类的成员变量:

    @Entity  
    @Table(name="t_group")//group在sql中是关键词,避免冲突  
    public class Group {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        @Column(unique = true)//利用unique约束禁止重复数据  
        private String name;  
    }  
       
    @Entity  
    @Table(name="t_user")  
    public class User {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)   
        private int id;  
       
        private String name;  
       
        @ManyToOne(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)  
        @JoinColumn(name = "group_id")  
        private Group group;  
    }  
   fetch = FetchType.EAGER表示加载user时加载group,多对一的时候,默认为EAGER

3. 双边一对多、多对一

    比如一个组(Group)里有多个用户(User),Group类中有存储User的集合,User类中有Group类的成员变量:

    @Entity  
    @Table(name="t_group")  
    public class Group {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        private String name;  
       
        @OneToMany(mappedBy = "group")//表示已经在User类中对group做了映射了。一般有双向关联的都要设置mappedBy   
        private Set<User> users = new HashSet<User>();  
    }  
       
    @Entity  
    @Table(name="t_user")  
    public class User {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)   
        private int id;  
       
        private String name;  
       
        @ManyToOne(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)  
        @JoinColumn(name = "group_id")  
        private Group group;  
    }  
    双边关系中,控制权一般交给多方,因此这里@OneToMany没有配置数据库的外键列,而只配置了一个mappyedBy属性,告诉Hibernate,配置信息要到Student类中的group属性中去找。 

4. 单边多对多和双边多对多

    单边多对多:比如老师(Teacher)有多个(Student),学生也有多个老师,但是只有Teacher类中有存储Student类的集合:

    @Entity  
    public class Teacher {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)   
        private int id;  
       
        private String name;      
       
        @ManyToMany  
        @JoinTable(  
            name = "t_s",//第三张中间表名  
            joinColumns = {@JoinColumn(name="teacher_id")},//第三张表中针对本表主键字段名称  
            inverseJoinColumns = {@JoinColumn(name="student_id")}//第三张表中针对对方(student)表中主键名称  
            )  
        private Set<Student> students = new HashSet<Student>();  
    }  
       
    @Entity  
    public class Student {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)    
        private int id;  
       
        private String name;  
    }  
    双边多对多只要在Student类中添加存储Teacher类的集合即可,并配有mappedBy属性。
    @ManyToMany(mappedBy="students")  
    private Set<Teacher> teachers = new HashSet<Teacher>();  

5. 主键相同的单边一对一和双边一对一

    由于两个实体类是一对一的关系,因此可以设置两个实体类使用相同的主键。反过来,具有相同主键的实体被视为一对一的关系。

    针对上面一对一关系的例子,通过主键相同的方法如下:

    单边一对一:

    @Entity  
    @Table(name = "student")  
    public class Student {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)   
        private String id;  
       
        private String name;  
       
        @OneToOne(cascade = {CascadeType.ALL})  
        @PrimaryKeyJoinColumn  
        private StudentCard stuCard;  
    }  
       
    @Entity  
    @Table(name = "studentid")  
    public class StudentCard {  
        @Id  
        //这里不能使用自增长了   
        private String id;  
       
        private int num;  
    }  

    双边一对一:

    @Entity  
    public class Husband {  
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
       
        private String name;  
       
        @OneToOne  
        @PrimaryKeyJoinColumn  
        private Wife wife;  
    }  
       
    @Entity  
    public class Wife {  
        @Id  
        //这里不能使用自增长了   
        private int id;  
       
        private String name;  
       
        @OneToOne  
        @PrimaryKeyJoinColumn  
        private Husband husband;  
    }  

        要注意的是save Husband和Wife的时候,先session.save(husband),在session.save(wife)之前要先设置wife的id和husband相同,即:wife.setId(husband.getId())  

        以上就是hibernate中实体关系映射的几种情况。如有错误,欢迎留言指正~

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!

-----更多文章请看:http://blog.csdn.net/eson_15
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值