- 浏览: 919434 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (537)
- Java SE (114)
- Struts (18)
- Hibernate (25)
- Spring (3)
- Page_Tech (41)
- Others (87)
- Database (29)
- Server (24)
- OpenSource_Tools (15)
- IDE_Tool (22)
- Algorithm (28)
- Interview (22)
- Test (28)
- Hardware (1)
- Mainframe (25)
- Web application (4)
- Linux (3)
- PHP (17)
- Android (1)
- Perl (6)
- ubuntu (1)
- Java EE (9)
- Web Analysis (5)
- Node.js (2)
- javascript (2)
最新评论
-
一键注册:
request.getRequestURL()和request.getRequestURI() -
SuperCustomer:
...
SED的暂存空间和模式空间 -
juyo_ch:
讲得挺好理解的,学习了
java 死锁及解决 -
chinaalex:
最后一题答案正确,但是分析有误.按照如下过程,上一行为瓶,下一 ...
zz智力题 -
liaowuxukong:
多谢博主啦,弱弱的了解了一点。
C++/Java 实现多态的方法(C++)
[正文]:
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还是很有用的,只是用错了地方。
发表评论
-
hibernate n+1问题
2010-10-21 11:05 940Hibernate中常会用到set,bag等集合表示1对多的关 ... -
Hibernate 关联关系 总结
2010-09-09 15:27 9681.一对多的单向关联关系 配置单向的一对多关系是 ... -
Hibernate 关联
2010-09-09 15:24 10081、hibernate多对一关联映 ... -
Hibernate中No row with the given identifier exists问题的原因及解决
2010-06-23 09:54 963产生此问题的原因: ... -
Hibernate使用count(*)取得表中记录总数(跨Hibernate3.x版本问题)
2010-06-22 17:13 1537Java代码 /** * @T ... -
hibernate继承关系映射
2010-06-13 16:58 927hbn 的继承映射关系有这 ... -
Hibernate集合映射
2010-06-13 12:49 920准备找工作,重新整理一下Hibernate,今天做了集合映射 ... -
高并发网站的架构
2010-05-07 11:07 724我在CERNET做过拨号接入平台的搭建,而后在Yaho ... -
Hibernate事务和并发控制
2010-05-07 10:21 9221. 事务介绍:1.1. 事务的定义:事务就 ... -
hibernate中lazy的使用
2009-12-18 22:00 785lazy,延迟加载 Lazy的 ... -
Hibernate中代码自动生成功能小结
2009-12-06 15:10 1041Hibernate中需要class和mapping file, ... -
hibernate工具箱—根据映射文件自动建表
2009-12-04 12:08 985public class ExportDB { ... -
关联加载对象时的报错-----a different object with the same identifier value
2009-11-18 16:13 896因为在hibernate中同一个session里面有了两个相同 ... -
update/saveOrUpdate/merge
2009-11-18 15:28 1148通常下面的场景会使用update()或saveOrUpdate ... -
写得很不错的-Hibernate中的实体状态(二)
2009-11-18 15:08 957(2)session.merge ()方法 ... -
写得很不错的-Hibernate中的实体状态(一)
2009-11-18 15:04 1144持久层的解决方案有许 ... -
Hibernate3.x总结
2009-11-18 14:29 762Hibernate不是盏省油的灯 ... -
Hibernate Annotation几种关联映射
2009-11-02 17:01 1086Hibernate Annotation几种关联映射 一对一 ... -
hibernate3的注解映射学习
2009-11-02 16:41 1351注解映射必须满足两大条件:Hibernate3.2以上版本和J ... -
Hibernate 中级联操作 cascade 选项
2009-11-02 16:35 932none :在保存、更新或删除对象时,忽略其他关联的对象。他是 ...
相关推荐
**标题:“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中,我们...