作为一个ORM框架,hibernate肯定也需要满足我们实现表与表之间进行关联的需要。hibernate在关联方法的实现很简单。下面我们先来看看一对一的做法:
不多说了,我们直接上代码:
两个实体类,TUser和TPassport:
public class TUser implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private int age;
private String name;
private TPassport passport;
//省略Get/Set方法
}
public class TPassport implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String serial;
private int expiry;
private TUser user;
//省略Get/Set方法
}
下面我们看一下映射文件有什么不同:
<hibernate-mapping package=\"org.hibernate.tutorial.domain4\">
<class name=\"TUser\" table=\"USER4\">
<id name=\"id\" column=\"id\">
<generator class=\"native\" />
</id>
<property name=\"name\" type=\"java.lang.String\" column=\"name\"/>
<property name=\"age\" type=\"java.lang.Integer\" column=\"age\"/>
<one-to-one name=\"passport\" class=\"TPassport\"
cascade=\"all\" outer-join=\"true\" />
</class>
</hibernate-mapping>
这里我们看到有一个新标签,one-to-one,它表明当前类与所对应的类是一对一的关系,cascade是级联关系,all表明无论什么情况都进行级联,即当对TUser类进行操作时,TPassport也会进行相应的操作,outer-join是指是否使用outer join语句。
我们再看另外一个TPassport的映射文件:
<hibernate-mapping package=\"org.hibernate.tutorial.domain4\">
<class name=\"TPassport\" table=\"passport4\">
<id name=\"id\" column=\"id\">
<generator class=\"foreign\" >
<param name=\"property\">user</param>
</generator>
</id>
<property name=\"serial\" type=\"java.lang.String\" column=\"serial\"/>
<property name=\"expiry\" type=\"java.lang.Integer\" column=\"expiry\"/>
<one-to-one name=\"user\" class=\"TUser\" constrained=\"true\" />
</class>
</hibernate-mapping>
这里我们重点看到generator的class值,它为foreign表明参照外键,而参照哪一个是由param来进行指定,这里表明参照User类的id。而one-to-one标签中多了一个constrained属性,它是告诉hibernate当前类存在外键约束,即当前类的ID根据TUser的ID进行生成。
下面我们直接上测试类,这次测试类没有用JUnit而是直接Main方法来了:
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
TUser user = new TUser();
user.setAge(20);
user.setName(\"shunTest\");
TPassport passport = new TPassport();
passport.setExpiry(20);
passport.setSerial(\"123123123\");
passport.setUser(user);
user.setPassport(passport);
session.save(user);
session.getTransaction().commit();
}
代码很简单,就不说了。我们主要看这里:
session.save(user);
这里为什么我们只调用一个save呢,原因就在我们的TUser映射文件中的cascade属性,它被设为all,即表明当我们对TUser进行保存,更新,删除等操作时,TPassport也会进行相应的操作,所以这里我们不用写session.save(passport)。我们看到后台:
Hibernate: insert into USER4 (name, age) values (?, ?) Hibernate: insert into passport4 (serial, expiry, id) values (?, ?, ?)
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
TUser user = (TUser)session.load(TUser.class,new Integer(3));
System.out.println(user.getName()+\":\"+user.getPassport().getSerial());
}
外键关联
现在我们看一下通过外键来进行关联的一对一关联。
还是一贯的直接上例子:我们写了两个实体类,TGroup和TUser
public class TGroup implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private TUser user;
//省略Get/Set方法
}
public class TUser implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private int age;
private String name;
private TGroup group;
//省略Get/Set方法
}
实体类完了我们就看一下映射文件:
<hibernate-mapping package=\"org.hibernate.tutorial.domain5\"> <class name=\"TUser\" table=\"USER5\"> <id name=\"id\" column=\"id\"> <generator class=\"native\" /> </id> <property name=\"name\" type=\"java.lang.String\" column=\"name\"/> <property name=\"age\" type=\"java.lang.Integer\" column=\"age\"/> <many-to-one name=\"group\" class=\"TGroup\" column=\"group_id\" unique=\"true\" /> </class> </hibernate-mapping>
这里我们看到是用many-to-one标签而不是one-to-one,为什么呢?
这里以前用的时候也没多在注意,反正会用就行,但这次看了夏昕的书终于明白了,实际上这种通过外键进行关联方式只是多对一的一种特殊方式而已,我们通过unique=\"true\"限定了它必须只能有一个,即实现了一对一的关联。
接下来我们看一下TGroup的映射文件:
<hibernate-mapping package=\"org.hibernate.tutorial.domain5\"> <class name=\"TGroup\" table=\"group5\"> <id name=\"id\" column=\"id\"> <generator class=\"native\" /> </id> <property name=\"name\" type=\"java.lang.String\" column=\"name\"/> <one-to-one name=\"user\" class=\"TUser\" property-ref=\"group\" /> </class> </hibernate-mapping>
这里,注意,我们又用到了one-to-one,表明当前的实体和TUser是一对一的关系,这里我们不用many-to-one,而是通过one-to-one指定了TUser实体中通过哪个属性来关联当前的类TGroup。这里我们指定了TUser是通过group属性和Tuser进行关联的。property-ref指定了通过哪个属性进行关联。
下面我们看测试类:
public class HibernateTest {
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
TGroup group = new TGroup();
group.setName(\"testGroup\");
TUser user = new TUser();
user.setAge(23);
user.setName(\"test\");
user.setGroup(group);
group.setUser(user);
session.save(group);
session.save(user);
session.getTransaction().commit();
session.close();
}
}
注意,这次我们的代码中需要进行两次的保存,因为它们对各自都有相应的对应,只保存一个都不会对另外一个有什么操作。所以我们需要调用两次保存的操作。最后进行提交。
hibernate打印出语句:
Hibernate: insert into group5 (name) values (?) Hibernate: insert into USER5 (name, age, group_id) values (?, ?, ?)
这说明我们正确地存入了两个对象值。
我们写多一个测试类进行查询:
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
TUser user = (TUser)session.load(TUser.class,new Integer(1));
System.out.println(\"From User get Group:\"+user.getGroup().getName());
TGroup group = (TGroup)session.load(TGroup.class,new Integer(1));
System.out.println(\"From Group get User:\" + group.getUser().getName());
session.close();
}
我们都可以得到正确的结果,这表明我们可以通过两个对象拿出对方的值,达到了我们的目的。
这个例子中用到的TGroup和TUser只是例子而已,实际上现实生活中的user一般都对应多个group。
本文地址:https://www.stayed.cn/item/9701
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我