最近研究Hibernate,试了一个数据库表项多对一的例子,结果给失败了。最后在网上找了一个博客看了看恍然大悟。启发我的这篇博客地址:http://blog.csdn.net/yinbodotcc/article/details/1505445
现在总结几点,我认识的误区:
1,无需在数据库建表的时候指定外键,Hibernate可以将两张无外键关联的表通过xml映射出来。
2,不要过度依赖Eclipse的自动生成的*.java类和*.hbm.xml(和数据库表映射的类和对应的xml文件),虽然在数据库表中那个意义上的外键(无需再建表时指定)是int型的,而在自动生成的java文件中也是自动生成了Integer型的;但是,切记,一定要自己动手将其修改为那个依赖的类的类型。
3,<many-to-one>中的class一定要写依赖类的完整路径。
4,出现错误:
could not initialize proxy - no Session 的原因是:session已经关闭了。
现在上代码看看:
1,建立数据库:(无需指定外键)
2,自动生成映射类:
Room:
package com.wjy.models;
// Generated 2014-1-21 10:36:04 by Hibernate Tools 3.4.0.CR1
/**
* Room generated by hbm2java
*/
public class Room implements java.io.Serializable {
private Integer id;
private String address;
public Room() {
}
public Room(String address) {
this.address = address;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
}
User:
package com.wjy.models;
// Generated 2014-1-21 10:36:04 by Hibernate Tools 3.4.0.CR1
/**
* User generated by hbm2java
*/
public class User implements java.io.Serializable {
private Integer id;
private String name;
private Room room; //注意这里,这里自动生成的是Integer,手动改成Room类型的。
public User() {
}
public User(String name) {
this.name = name;
}
public User(String name, Room room) {
this.name = name;
this.room = room;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Room getRoom() {
return room;
}
public void setRoom(Room room) {
this.room = room;
}
}
3,和2同时生成的 *.hbm.xml:
Room:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-1-21 10:36:04 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.wjy.models.Room" table="room" catalog="multone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="address" type="string">
<column name="address" length="100" not-null="true" />
</property>
</class>
</hibernate-mapping>
User:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-1-21 10:36:04 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.wjy.models.User" table="user" catalog="multone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="100" not-null="true" />
</property>
<many-to-one name="room" column="room_id" class="com.wjy.models.Room" cascade="all" outer-join="true">
</many-to-one> 注意:这里修改了,不是自动生成的那个了。room是*.java中的,room_id是数据库表中的那个字段。
</class>
</hibernate-mapping>
4,在hibernate.hbm.xml中添加映射:
<mapping class="com.wjy.models.Room" resource="com/wjy/models/Room.hbm.xml"/>
<mapping class="com.wjy.models.User" resource="com/wjy/models/User.hbm.xml"/>
5,现在可以看看测试代码了:
public void addUsers(){
//向数据库user表中添加两个用户:Wjy和Yhw,他们是舍友。运行程序会发现,room表中竟然也自动添加了宿舍号的记录。
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
//打开一个session实例
Session session=sessionFactory.openSession();
//开始事务
Transaction transaction=session.beginTransaction();
Room room1 = new Room();
room1.setAddress("96#");
User user1 = new User();
user1.setName("Wjy");
user1.setRoom(room1);
User user2 = new User();
user2.setName("Yhw");
user2.setRoom(room1);
//插入更新数据库
session.save(user1);
session.save(user2);
//session.saveOrUpdate(model);
transaction.commit();
session.close();
}
看看数据库的变化:
6,目前为止实现了多对一的映射,而无需再数据库表中指定,很灵活。
public void getRoom(){
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
//打开一个session实例
Session session=sessionFactory.openSession();
//开始事务
Transaction transaction=session.beginTransaction();
String hql="from User where name='Yhw'";
Query userList=session.createQuery(hql);
List list=userList.list();
//User user = (User) session.load(User.class, new Integer(1));
//transaction.commit();
Iterator iterator=list.iterator();
User user=(User)iterator.next();
System.out.println(user.getName()+" in "+user.getRoom().getAddress());
//System.out.println(user.getName()+" in "+user.getRoom().getAddress());
session.close();
}
以上程序展示了两种查询到User的方式,被注释掉的是第二种方法。
我将我的源代码传上来,供大家参考。