- 浏览: 203523 次
- 性别:
- 来自: 芜湖
文章分类
- 全部博客 (139)
- 软件 (0)
- Pattern (6)
- CSDN导入 (19)
- Struts (3)
- [网站分类]1.网站首页原创 (27)
- [网站分类]6.转载区 (4)
- Hibernate (10)
- Error (8)
- [网站分类]2.Java新手区 (20)
- Java (8)
- [网站分类]4.其他技术区 (10)
- Web (1)
- C++ (2)
- Algorithm (4)
- Linux (2)
- Skill (1)
- Tech (2)
- Note (2)
- [网站分类]3.非技术区 (1)
- Database (1)
- Winty (7)
- [网站分类]1.网站首页原创Java技术区(对首页文章的要求: 原创、高质量、经过认真思考并精心写作。BlogJava管理团队会对首页的文章进行管理。) (0)
最新评论
-
haohao-xuexi02:
很不错哦。
O'Reilly cos上传组件的使用(1/3) - 上传文件 -
yoin528:
useUnicode=true&charact ...
[原]向MySQL数据库插入Blob数据的问题 -
xiaoqing20:
下载来看看!呵呵
[原]Struts2类型转换 -
xiaoqing20:
[原]Struts2类型转换
[标题]:Hibernate一对多(单向)
[时间]:2009-6-12
[摘要]:单向一对多关联只需要在"一方"进行配置即可,"多方"无需额外配置。
[关键字]:外键,inverse,Hibernate,Set,一对多,单向,ORM,mapping,关系数据库,映射
[环境]:MyEclipse7 , JDK6,Hibernate3.2,Tomcat6,MySQL 5.1.34-community
[作者]:Winty (wintys@gmail.com) http://www.blogjava.net/wintys
[正文]:
Hibernate一对多关联,例如一个用户有多张银行卡(只考虑用户到银行卡的单向一对多关联)。由于是学习Hibernate原理,并没有使用工具自动生成代码等。
单向一对多关联只需要在"一方"进行配置即可,"多方"无需额外配置。
a.Java程序中所要做的一对多:
public class User{
...
private Set<Card> cards;
...
}
public class Card{
...
}
b.Hibernate中所要做的一对多:
User.hbm.xml:
...
<set name="cards" inverse="false" cascade="all">
<key column="userId" />
<one-to-many class="wintys.hibernate.onetomany.Card" />
</set>
...
c.数据库中的一对多:
而对应的数据库中,只要相应在Card对应的物理表中添加外键userId(不要设为NOT NULL)即可。
详细的MyEclipse WebProject如下:
1、实体类:
用户类User.java:
import java.util.Set;
public class User {
private String id;
private String name;
private Set<Card> cards;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setCards(Set<Card> cards) {
this.cards = cards;
}
public Set<Card> getCards() {
return cards;
}
}
银行卡类Card.java:
public class Card {
private String id;
private float balance;
public Card(){
}
public Card(float balance){
this.balance = balance;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public float getBalance() {
return balance;
}
public void setBalance(float balance) {
this.balance = balance;
}
}
2、数据库表:
数据库是MySQL 5.1.34-community。
用户表:
id VARCHAR(50) NOT NULL,
name VARCHAR(100),
PRIMARY KEY(id)
);
银行卡表:
id VARCHAR(50) NOT NULL,
balance FLOAT(7,2),
userId VARCHAR(50),
PRIMARY KEY(id)
);
3、映射文件:
用户类映射文件/src/wintys/hibernate/onetomany/User.hbm.xml:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="wintys.hibernate.onetomany.User" table="myuser" catalog="db">
<id name="id" type="string">
<column name="id" not-null="true"/>
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String" column="name" />
<set name="cards" inverse="false" cascade="all">
<key column="userId" />
<one-to-many class="wintys.hibernate.onetomany.Card" />
</set>
</class>
</hibernate-mapping>
银行卡映射文件/src/wintys/hibernate/onetomany/User.hbm.xml:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="wintys.hibernate.onetomany.Card" table="mycard" catalog="db">
<id name="id" type="string">
<column name="id" not-null="true"/>
<generator class="uuid.hex" />
</id>
<property name="balance" />
</class>
</hibernate-mapping>
Hibernate配置文件:/src/hibernate.cfg.xml:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="myeclipse.connection.profile">MySQLDriver</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="show_sql">true</property>
<mapping resource="wintys/hibernate/onetomany/User.hbm.xml" />
<mapping resource="wintys/hibernate/onetomany/Card.hbm.xml" />
</session-factory>
</hibernate-configuration>
4、使用测试:
/src/wintys/hibernate/onetomany/HibernateDAO.java:
import java.util.List;
public interface HibernateDAO {
public void insert();
public List<User> selectAll();
}
/src/wintys/hibernate/onetomany/HibernateDAOBean.java:
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class HibernateDAOBean implements HibernateDAO {
public void insert() throws HibernateException {
Transaction tc = null;
try{
Set<Card> cards = new HashSet<Card>();
Card c1,c2,c3;
c1 = new Card(7641.96f);
c2 = new Card(654.8f);
c3 = new Card(3650f);
cards.add(c1);
cards.add(c2);
cards.add(c3);
User user = new User();
user.setName("Tom");
user.setCards(cards);
Session session = HibernateUtil.getSession();
tc = session.beginTransaction();
/*
配置文件中的cascade="true"时,所以无需手动保存c1,c2,c3
session.save(c1);
session.save(c2);
session.save(c3);
*/
session.save(user);
tc.commit();
}catch(HibernateException e){
try{
if(tc != null)
tc.rollback();
}catch(Exception ex){
System.err.println(ex.getMessage());
}
System.err.println(e.getMessage());
}finally{
HibernateUtil.closeSession();
}
}
@SuppressWarnings("unchecked")
public List<User> selectAll() throws HibernateException {
List<User> users = null;
Transaction tc = null;
try{
Session session = HibernateUtil.getSession();
tc = session.beginTransaction();
Query query = session.createQuery("from User");
users = query.list();
tc.commit();
}catch(HibernateException e){
try{
if(tc != null){
tc.rollback();
users = null;
}
}catch(Exception ex){
System.err.println(ex.getMessage());
}
System.err.println(e.getMessage());
}finally{
//HibernateUtil.closeSession();
}
return users;
}
}
/src/wintys/hibernate/onetomany/HibernateUtil.java:
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate Session管理
* @author Winty
*/
public class HibernateUtil {
private static SessionFactory factory = null;
private static ThreadLocal<Session> threadLocal;
static {
try{
factory = new Configuration()
.configure()
.buildSessionFactory();
}catch(HibernateException e){
System.err.println(e.getMessage());
}
threadLocal = new ThreadLocal<Session>();
}
private HibernateUtil(){
}
public static Session getSession()throws HibernateException{
Session session = threadLocal.get();
if(session == null){
session = factory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession()throws HibernateException{
Session session = threadLocal.get();
if(session != null){
session.close();
}
threadLocal.set(null);
}
}
/index.jsp:
<%@ page import="wintys.hibernate.onetomany.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<%
List<User> users = null;
HibernateDAO dao = new HibernateDAOBean();
dao.insert();
users = dao.selectAll();
Iterator<User> it = users.iterator();
while(it.hasNext()){
User user = it.next();
String id = user.getId();
String name = user.getName();
out.println("id:" + id + "<br />");
out.println("name:" + name + "<br />");
out.println("cards:<br />");
Set<Card> cards = user.getCards();
Iterator<Card> itc = cards.iterator();
while(itc.hasNext()){
Card card = itc.next();
String cardId = card.getId();
float balance = card.getBalance();
out.println(" cardId:" + cardId + "<br />");
out.println(" balance:" + balance + "<br />");
}
out.println("<hr/>");
}
%>
</body>
</html>
5、运行结果:
控制台显示:
Hibernate: insert into db.myuser (name, id) values (?, ?)
Hibernate: insert into db.mycard (balance, id) values (?, ?)
Hibernate: insert into db.mycard (balance, id) values (?, ?)
Hibernate: insert into db.mycard (balance, id) values (?, ?)
Hibernate: update db.mycard set userId=? where id=?
Hibernate: update db.mycard set userId=? where id=?
Hibernate: update db.mycard set userId=? where id=?
......
index.jsp页面显示:
id:402881e421d4d0be0121d4d20e140005
name:Tom
cards:
cardId:402881e421d4d0be0121d4d20e230008
balance:654.8
cardId:402881e421d4d0be0121d4d20e230006
balance:7641.96
cardId:402881e421d4d0be0121d4d20e230007
balance:3650.0
6、注意的问题:
a、错误提示:Field 'userId' doesn't have a default value。
一开始把"userId"设成NOT NULL,但是Hibernate先执行的是:
"insert into db.mycard (balance, id) values (?, ?)"
然后才执行"update db.mycard set userId=? where id=?",
而userId在insert时是没有写入值的,所以就会报错。把userId的NOT NULL去掉即可。
b、User.hbm.xml中要设置cascade="all",或其它有效值,不然,在保存User对象时,相关的Card对象不会被保存。
c、User.hbm.xml中set标签的inverse属性不能设置为"true",inverse的默认值是"false",所以不加
inverse也可以。看书上说:在一对多的关联关系实现中,最好设置inverse="true",将有助于性能的改善。所以一开始就用了
inverse="true",User和Card对象都分别正确写入数据库了,但是就是userId字段没有被自动写入。
myuser表:
+--------------------------------------------+------+
| id | name |
+--------------------------------------------+------+
| 402881e421d4d0be0121d4d20e140005 | Tom |
+--------------------------------------------+------+
mycard表:
+--------------------------------------------+---------+---------
| id | balance | userId
+--------------------------------------------+---------+---------
| 402881e421d4d0be0121d4d20e230006 | 7641.96 | NULL
| 402881e421d4d0be0121d4d20e230007 | 3650.00 | NULL
|
| 402881e421d4d0be0121d4d20e230008 | 654.80 | NULL
+--------------------------------------------+---------+---------
搞了半天,原来在本例应该把inverse设为false。inverse还是很有用的,只是用错了地方。
[参考资料]:
[1] Hibernate 一对多外键单向关联--熔 岩 : http://lavasoft.blog.51cto.com/62575/39317
[2] Hibernate应用(二)单向一对多及双向一对多的配置: http://suhaoyuan.spaces.live.com/Blog/cns!2659D3AC8253C554!217.entry
[3] Hibernate单向一对多应注意的问题 : http://blog.chinaunix.net/u2/88320/showart_1716296.html
[4] hibernate一对多例子-已更新(二) : http://www.blogjava.net/wujun/archive/2008/08/04/39700.html
作者:Winty (wintys@gmail.com)
博客:http://www.blogjava.net/wintys
发表评论
-
Hibernate继承映射-继承关系中每个类均映射为一个数据库表
2009-07-14 22:49 1744[标题]:[原]Hibernate继承映射-继承关系中每个类均 ... -
[原]Hibernate一对多(双向)
2009-06-17 22:04 1930[标题]:Hibernate一对多(双向) [时间]:2009 ... -
[原]在MyEclipse中开发Hibernate入门
2009-06-17 22:21 925[标题]:在MyEclipse中开发Hibernate入门 ... -
[原]Hibernate多对多(单向)
2009-06-19 22:43 887[标题]:[原]Hibernate多对多(单向) [时间]:2 ... -
[原]Hibernate多对多(双向)
2009-06-19 22:50 1105[标题]:[原]Hibernate多对多(双向) [时间]: ... -
[原]Hibernate继承映射-具体类映射为数据库表
2009-06-21 13:05 1078[标题]:[原]Hibernate继承映射-具体类映射为数据库 ... -
[原]Hibernate继承映射-整个类层次映射为单个数据库表
2009-06-21 13:17 825[标题]:[原]Hibernate继承映射-整个类层次映射为单 ... -
Hibernate继承映射-概述
2009-06-21 14:24 1073Hibernate中对继承关系的 ... -
[原]Hibernate集合映射
2009-07-03 23:50 1467[标题]:[原]Hibernate集合映射 [时间]:200 ...
相关推荐
**标题:“Hibernate一对多单向关联映射”** 在Java持久化框架Hibernate中,一对多关系是常见的数据关联模式,它表示一个实体可以与多个其他实体相关联。在这个主题中,我们将深入探讨如何在Hibernate中实现一对多...
在本教程中,我们将探讨如何使用注解和XML配置实现Hibernate的一对多单向关联。 首先,让我们理解一对多关联的概念。在数据库中,一对多关联意味着在一个表(父表)中的一个记录可以对应另一个表(子表)中的多个...
以上就是关于Hibernate中实现多对一单向关联关系的基本知识,包括如何在实体类中定义关联、如何进行数据库操作以及如何查询关联对象。这个源代码示例应该提供了更具体的实现细节,你可以通过查看和运行它来深入理解...
本项目“Hibernate学习:单向多对一关联 工程”专注于讲解Hibernate中的单向多对一关联映射,这是数据库设计中常见的关系类型,尤其在处理具有层次结构的数据时。 单向多对一关联指的是在一个实体类中有一个引用,...
本教程聚焦于Hibernate中的单向一对多关联映射,这是一个常见的实体关系模型,广泛应用于各种业务场景。 在数据库设计中,一对多关系意味着一个父表记录可以与多个子表记录相关联。例如,一个学生可以有多个课程,...
标题 "Hibernate基于连接表的一对多单向关联" 涉及的是数据库对象关系映射(ORM)框架Hibernate中的一个重要概念。在Java开发中,Hibernate是广泛使用的工具,它允许开发者将Java类与数据库表进行映射,简化了数据...
“Hibernate基于外键的一对多单向关联”这个标题指的是在Java持久化框架Hibernate中,如何通过外键实现一个实体类(如订单)与另一个实体类(如商品)之间的一对多关系,并且这种关联是单向的,即从订单端可以访问到...
总结来说,Hibernate中的多对多单向关联是一种高效的数据映射方式,它允许我们在不增加复杂性的情况下处理两个实体之间的复杂关系。通过学习和实践,开发者能够更好地掌握这种关联类型,从而在实际项目中灵活运用。
在Java持久化框架Hibernate中,一对多外键单向关联是一种常见的关系映射方式,它描述了一对多的关系,其中一个实体(例如Person)可以与多个其他实体(例如Address)相关联,而关联的方向只从多方(Address)指向...
在Java的持久化框架Hibernate中,单向一对多关联映射是常见的数据关系处理方式,尤其是在处理数据库中的实体类和表之间的关系时。本主题主要关注如何使用注解来实现这种映射。Hibernate通过注解使得对象关系映射...
3. `@JoinColumn`: 定义一对一或一对多关系中的外键字段,这里用在`@JoinTable`中,表示多对多关系的连接表中外键的属性。 在上述代码中,`Student`实体有一个`courses`集合,它包含了与之关联的所有`Course`实体。...
在本主题"Hibernate单向一对多关联映射(XML版)"中,我们将深入探讨如何使用XML配置来实现数据库中一个实体类对应多个实体类的关联关系。 在Hibernate中,一对多关联是一种常见的关系映射类型,它反映了数据库中的...
本练习主要关注的是Hibernate中的单向多对多关联映射,这是一种常见的关系数据库设计模式,用于表示两个实体间复杂的关系。 在多对多关联中,两个实体类可以相互拥有多个实例,但只在一个方向上建立关联。例如,...
本篇文章将深入探讨Hibernate中注解的一对多、多对多和一对一关系映射。 ### 一对多关系 在现实生活中,例如一个班级有一个班主任,而班主任可以管理多个学生,这就是典型的“一对多”关系。在Hibernate中,我们...