Hibernate使用注解方式完成双向多对多映射

来源:互联网 发布:淘宝双11交易数据 编辑:程序博客网 时间:2024/05/23 15:46

前面的关于Hibernate的文章讲解的知识比较多了,今天这篇文章就不铺垫了,直接上代码,我们一起来看看注释。今天使用的关系是人与地址的关系,例子找的不太好,忍耐一下!

先看持久化类(注解是重点):

Person:

@Entity@Table(name="person_inf")// 多对多的映射必须存在一个中间表public class Person {// 标识属性@Id@Column(name="person_id")// 设置主键的映射策略@GeneratedValue(strategy=GenerationType.IDENTITY)private Integer id;private String name;private int age;// 定义该Person实体所有关联的Address实体@ManyToMany(targetEntity=Address.class)// 映射连接表,指定连接表的名字是person_address@JoinTable(name="person_address",// 映射连接表中名为person_id的外键列,该列参照当前实体对应表的person_id主键列joinColumns = @JoinColumn(referencedColumnName="person_id",name="person_id"),// 映射连接表中名为address_id的外键列,该列参照当前实体的关联实体对应标的address_id主键列inverseJoinColumns = @JoinColumn(referencedColumnName="address_id",name="address_id"))private Set<Address> addresses = new HashSet<>();// 省略set、get方法以及构造器方法...}

Address:

@Entity@Table(name="address_inf")public class Address {@Id@Column(name="address_id")@GeneratedValue(strategy=GenerationType.IDENTITY)private int addressId;private String addressDetail;@ManyToMany(targetEntity=Person.class)@JoinTable(name="person_address",joinColumns=@JoinColumn(referencedColumnName="address_id",name="address_id"),inverseJoinColumns=@JoinColumn(referencedColumnName="person_id",name="person_id"))private Set<Person> persons = new HashSet<>();// 省略set、get方法以及构造器方法...}

然后cfg核心配置文件的配置与之前有点不同,现在不存在hbm配置文件,Annotation都存在于持久化类中,直接如下配置:

<mapping class="edu.ctgu.hibernate.many2many.Person"/><mapping class="edu.ctgu.hibernate.many2many.Address"/>

测试方法:

public class Many2Many {private SessionFactory factory = null;private Session session = null;private Transaction transaction = null;@Beforepublic void testBefore(){// 1.初始化配置文件加载配置信息,默认加载src目录下的hibernate.cfg.xml文件Configuration configuration = new Configuration().configure();// 2.初始化SessionFactoryfactory = configuration.buildSessionFactory();// 3.打开Sessionsession = factory.openSession();// 4.开启事务transaction = session.beginTransaction();}@Afterpublic void testAfter(){transaction.commit();session.close();factory.close();}@Testpublic void testGet(){Person person = session.get(Person.class, 10);System.out.println(person.getName());// 遍历与指定person关联的address类的集合Iterator<Address> iterator = person.getAddresses().iterator();while (iterator.hasNext()) {Address address = iterator.next();System.out.println(address);}}@Testpublic void testSave(){// 这就是基本的次序了Person p = new Person("饶大大",21);session.save(p);Address a = new Address("襄阳樊城");a.getPersons().add(p);session.save(a);Address a2 = new Address("武汉武昌");a2.getPersons().add(p);session.save(a2);Person p2 = new Person("爱丽丝",20);p2.getAddresses().add(a2);p2.getAddresses().add(a);session.save(p2);}@Testpublic void test(){}}

上面的测试方法值得讲解一下。首先在执行空的test测试方法时,Hibernate打印的SQL语句如下:
Hibernate:         create table address_inf (       address_id integer not null auto_increment,        addressDetail varchar(255),        primary key (address_id)    )Hibernate:         create table person_address (       address_id integer not null,        person_id integer not null,        primary key (person_id, address_id)    )Hibernate:         create table person_inf (       person_id integer not null auto_increment,        age integer not null,        name varchar(255),        primary key (person_id)    )Hibernate:         alter table person_address        add constraint FK2ppxjvtgnqmym2pcrnw1rxpmo        foreign key (person_id)        references person_inf (person_id)Hibernate:         alter table person_address        add constraint FKkkw06n97i6bwjpiohmqvby97        foreign key (address_id)        references address_inf (address_id)
创建了三个表,其中表person_address就是多对多映射中必须存在的连接表,然后再为连接表设置两个外键映射(其实连接表中的两个数据列为主键元组),分别映射主表的主键。

然后重点来了,我们看一下测试save的代码块,注意插入的顺序。开始一个Person对象被单一保存,然后设置两个地址关联到Person对象;最后一个Person直接关联两个Address对象。目前在我看来这是一个符合逻辑的执行次序。

其他方法大家一一测试,相信会学到很多的东西。

原创粉丝点击