- 浏览: 902780 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 905Hibernate中常会用到set,bag等集合表示1对多的关 ... -
Hibernate 关联关系 总结
2010-09-09 15:27 9441.一对多的单向关联关系 配置单向的一对多关系是 ... -
Hibernate 关联
2010-09-09 15:24 9741、hibernate多对一关联映 ... -
Hibernate中No row with the given identifier exists问题的原因及解决
2010-06-23 09:54 916产生此问题的原因: ... -
Hibernate使用count(*)取得表中记录总数(跨Hibernate3.x版本问题)
2010-06-22 17:13 1510Java代码 /** * @T ... -
hibernate继承关系映射
2010-06-13 16:58 893hbn 的继承映射关系有这 ... -
Hibernate集合映射
2010-06-13 12:49 900准备找工作,重新整理一下Hibernate,今天做了集合映射 ... -
高并发网站的架构
2010-05-07 11:07 702我在CERNET做过拨号接入平台的搭建,而后在Yaho ... -
Hibernate事务和并发控制
2010-05-07 10:21 8921. 事务介绍:1.1. 事务的定义:事务就 ... -
hibernate中lazy的使用
2009-12-18 22:00 760lazy,延迟加载 Lazy的 ... -
Hibernate中代码自动生成功能小结
2009-12-06 15:10 1013Hibernate中需要class和mapping file, ... -
hibernate工具箱—根据映射文件自动建表
2009-12-04 12:08 966public class ExportDB { ... -
关联加载对象时的报错-----a different object with the same identifier value
2009-11-18 16:13 860因为在hibernate中同一个session里面有了两个相同 ... -
update/saveOrUpdate/merge
2009-11-18 15:28 1129通常下面的场景会使用update()或saveOrUpdate ... -
写得很不错的-Hibernate中的实体状态(二)
2009-11-18 15:08 935(2)session.merge ()方法 ... -
写得很不错的-Hibernate中的实体状态(一)
2009-11-18 15:04 1124持久层的解决方案有许 ... -
Hibernate3.x总结
2009-11-18 14:29 732Hibernate不是盏省油的灯 ... -
Hibernate Annotation几种关联映射
2009-11-02 17:01 1057Hibernate Annotation几种关联映射 一对一 ... -
hibernate3的注解映射学习
2009-11-02 16:41 1327注解映射必须满足两大条件:Hibernate3.2以上版本和J ... -
Hibernate 中级联操作 cascade 选项
2009-11-02 16:35 913none :在保存、更新或删除对象时,忽略其他关联的对象。他是 ...
相关推荐
这里包含了hibernate多对一单向关联关系实现源码,希望对你有用。
博文链接:https://shaqiang32.iteye.com/blog/201314
NULL 博文链接:https://cdxs2.iteye.com/blog/1932864
Hibernate 系列教程 单向一对多
Hibernate 一对多 外键 单向关联,有例子。
Hibernate学习:单向多对一关联 工程
Hibernate 多对多单向关联 Hibernate 一对一外键双向关联 Hibernate 一对一主键双向关联 Hibernate 一对一连接表双向关联 Hibernate 一对多外键双向关联 Hibernate 一对多连接表双向关联 Hibernate 多对多双向关联
hibernate单向一对多关联映射(注解版)
Hibernate
hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了
该中有一对多,多对一,多对多,单向的双向都具有
NULL 博文链接:https://paladin1988.iteye.com/blog/1627678
NULL 博文链接:https://paladin1988.iteye.com/blog/1627597
包含《多对多双向关联映射》《多对一单向关联映射》《多对一双向关联映射》《一对多单向关联映射》等文档,并有图解及例子,非常适合新手学习,尤其是刚刚接触hibernate,对映射关系不清楚的。。。。
博文链接:https://llying.iteye.com/blog/220809