关联映射的关系(多对一)
1、 多对一:
多对一的实例分析:一个部门可以对应多个员工,那么员工就是多的一方,而部门就是一的一方,因此设置外键应该在员工表中。原因在于当hibernate执行时要先通过Configure读取配置文件中的信息并建立连接,在根据配置文件的信息对应映射文件,然后再将实体类映射成一个二维表。
在映射文件中生成外键:<many-to-one name=”depart” column=”depart_id”>
2、 分析图:
完成多对一关联的实例操作的源代码及其解析:
(1)首先在domain包下新建Department类,Employee类
在Department.java中:
a)要在Department.java类中封装属性 id,name
b)给这两个属性生成getter和setter方法
c)生成默认构造器
在Employee.java中:
a) 要在Employee.java类中封装id, name,还有一个Department类型的depart属性
b) 生成getter和setter方法
(2)编写映射文件,可根据根目录下的模板进行编写。要写这样两个映射文件:Department.hbm.xml。Employee.hbm.xml
a) Department.hbm.xml映射文件内容:
<!-- 实体类所在的包 -->
<hibernate-mapping
package="com.hbsi.domain">
<!-- 实体类的名字,如果表名和实体类的类名一样的话,那么就可以把table属性缺省 -->
<class name="Department" table="department">
<!-- Java类中的属性怎样和二维表中的字段建立关系,id是主键,特殊 .-1瞬时状态,非-1脱管状态-->
<id name="id" column="id">
<!-- 主键的一个生成器,主键生成器native,自增长的 -->
<generator class="native"/>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
b)Employee.hbm.xml映射文件:
<!-- 实体类所在的包 -->
<hibernate-mapping
package="com.hbsi.domain">
<!-- 实体类的名字,如果表名和实体类的类名一样的话,那么就可以把table属性缺省 -->
<class name="Employee" table="employee">
<!-- Java类中的属性怎样和二维表中的字段建立关系,id是主键,特殊 .-1瞬时状态,非-1脱管状态-->
<id name="id" column="id">
<!-- 主键的一个生成器,主键生成器native,自增长的 -->
<generator class="native"/>
</id>
<property name="name" column="name"/>
<!-- 多对一 ,外键的生成-->
<many-to-one name="depart" column="depart_id" not-null="true"/>
</class>
</hibernate-mapping>
(3)第三步编写配置文件,也可根据模板代码,将配置文件写入到配置文件中hibernate.cfg.xml。
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///user</property>
<property name="connection.username">root</property>
<property name="connection.password">1234</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="com/hbsi/domain/Department.hbm.xml"/>
<mapping resource="com/hbsi/domain/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
(4)工具类的编写,这样的代码我们都可以参照hibetnate工具类的模板代码的。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
//工具类
public final class HibernateUtil {
private static SessionFactory sessionFactory;
private HibernateUtil(){
}
static{
Configuration cfg=new Configuration();
cfg.configure();
sessionFactory=cfg.buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession(){
return sessionFactory.openSession();
}
}
(5)最后一步,我们就要编写测试类,来进行我们的测试了。编写测试类:Many2One.java
那么我们就来举例来编写一个查询的操作的方法:
static Employee query(int empId){
Session s=null;
Transaction tx=null;
try{
//得到session对象
s=HibernateUtil.getSession();
tx=s.beginTransaction();
//查询
Employee e=(Employee)s.get(Employee.class,empId);
//需要查询两个表。用懒加载将department中的name查询出来。
// System.out.println(e.getName()+e.getDepart().getName());
//解决懒加载.能够初始化代理对象
Hibernate.initialize(e.getDepart());
//提交事务
tx.commit();
return e;
}finally{
if(s!=null){
s.close();
}
}
}
在我们的main()方法中就可以调用query()这个方法了,代码如下:
//首先实例一个对象e1,查找id为1的员工,
Employee e1=query(1);
//会抛异常
//如果在这里查询,那么已经将资源释放,查询到department name时,还是懒加载,已经不再Session域中
//解决懒加载的问题:可以用到query()方法中的Hibernate.initialize(e.getDepart());.初始化搭理对象。就不会有异常了
System.out.println(e1.getName()+" "+e1.getDepart().getName());
运行结果如下: