2012年3月20日星期二
利用Dom4J的SAXReader解析大文件 - - ITeye技术网站
今天用到了对内容量很大的XML文件的解析,顺便记录一下。
关于XML的解析技术网上有很多文章,不再详述。 主要的方式有JDK自带的JAXP(Java API For XML Parser)、JDom、Dom4j等。其中Dom4J是相当灵活的,很多开源框架都基于Dom4J来做XML解析。
底层的解析器主要有两种: DOM、SAX。 其中DOM作为树型结构将文本装载到内存中,适合文本内容比较小的;SAX则按照流的方式扫描,事件触发的方式供你处理,比如遇到某个结点的开始符,结束符,大文本不能一次性装载到内存中,就应该采用SAX方式。
DOM4J利用SAXReader类来读取文件,然后为SAXReader对象设置元素处理解析器ElementHandler,有doStart和doEnd两个方法,分别在遇到元素的开始符号和结束符号时候触发。只需在相应的方法内实现自己的业务逻辑即可。
例子: XML文件结构如下:
view plaincopy to clipboardprint?<?xml version="1.0" encoding="GB2312"?>
<TESTINFO version="1.0">
<UPDATEINFO>
<PARAM_TIMESTAMP>2010-12-22 09:54:09</PARAM_TIMESTAMP>
<CITYINFO_LIST>
<CITYINFO City="591" Name="XYZ" No="334" />
<CITYINFO City="591" Name="BJD" No="335" />
<CITYINFO City="591" Name="UUS" No="390" />
</CITYINFO_LIST>
</UPDATEINFO>
</TESTINFO>
<?xml version="1.0" encoding="GB2312"?>
<TESTINFO version="1.0">
<UPDATEINFO>
<PARAM_TIMESTAMP>2010-12-22 09:54:09</PARAM_TIMESTAMP>
<CITYINFO_LIST>
<CITYINFO City="591" Name="XYZ" No="334" />
<CITYINFO City="591" Name="BJD" No="335" />
<CITYINFO City="591" Name="UUS" No="390" />
</CITYINFO_LIST>
</UPDATEINFO>
</TESTINFO>
其中CITYINFO可能是个很大的列表。 完整的程序代码如下:
view plaincopy to clipboardprint?package com.atu.xmltest;
import java.io.InputStream;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.ElementHandler;
import org.dom4j.ElementPath;
import org.dom4j.io.SAXReader;
public class MySaxHandler implements ElementHandler {
SAXReader reader;
public MySaxHandler() {
// test.xml文件跟类放在同一目录下
try {
InputStream is = MySaxHandler.class.getResourceAsStream("test.xml");
reader = new SAXReader();
reader.setDefaultHandler(this);
reader.read(is);
} catch (DocumentException e) {
e.printStackTrace();
}
}
@Override
public void onEnd(ElementPath ep) {
Element e = ep.getCurrent(); //获得当前节点
if(e.getName().equals("PARAM_TIMESTAMP"))
System.out.println("解析到时间:"+e.getText());
else if(e.getName().equals("CITYINFO")){
System.out.printf("解析到CITYINFO,属性值为:%s,%s,%s/n", e
.attributeValue("City"), e.attributeValue("Name"), e
.attributeValue("No"));
}
e.detach(); //记得从内存中移去
}
@Override
public void onStart(ElementPath ep) {
}
public static void main(String[] args){
new MySaxHandler();
}
}
package com.atu.xmltest;
import java.io.InputStream;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.ElementHandler;
import org.dom4j.ElementPath;
import org.dom4j.io.SAXReader;
public class MySaxHandler implements ElementHandler {
SAXReader reader;
public MySaxHandler() {
// test.xml文件跟类放在同一目录下
try {
InputStream is = MySaxHandler.class.getResourceAsStream("test.xml");
reader = new SAXReader();
reader.setDefaultHandler(this);
reader.read(is);
} catch (DocumentException e) {
e.printStackTrace();
}
}
@Override
public void onEnd(ElementPath ep) {
Element e = ep.getCurrent(); //获得当前节点
if(e.getName().equals("PARAM_TIMESTAMP"))
System.out.println("解析到时间:"+e.getText());
else if(e.getName().equals("CITYINFO")){
System.out.printf("解析到CITYINFO,属性值为:%s,%s,%s/n", e
.attributeValue("City"), e.attributeValue("Name"), e
.attributeValue("No"));
}
e.detach(); //记得从内存中移去
}
@Override
public void onStart(ElementPath ep) {
}
public static void main(String[] args){
new MySaxHandler();
}
}
运行结果:
解析到时间:2010-12-22 09:54:09
解析到CITYINFO,属性值为:591,XYZ,334
解析到CITYINFO,属性值为:592,BJD,335
解析到CITYINFO,属性值为:593,UUS,390
2012年3月19日星期一
hibernate一对多sort和order by_JAVA_百度空间
- 從資料庫的觀點來看,Set、Map、Bag是無序的,而List是有序的,這邊所謂的無序或有序,是指將容器中物件儲存至資料庫時,是否依容器物件中的順序來儲存。
- 然而從資料庫取得資料之後,您也許會希望Set、Map等容器中的物件可以依一定的順序來排列,您可以從兩個層次來容器中的物件排序,一是在載入資料後於JVM中排序,另一是在資料庫中直接使用order by子句來排序。
- 以 Set 這篇文章中的範例來作說明,要在JVM中就資料進行排序,您可以在映射文件中使用sort屬性來定義容器的排序,這適用於Set與Map,例如:
- User.hbm.xml
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="onlyfun.caterpillar.User" table="user">
- ....
- <set name="emails" table="email" sort="natural">
- <key column="id"/>
- <element type="java.lang.String"
- column="address"/>
- </set>
- </class>
- </hibernate-mapping>sort="natural"表示使用物件的comparaTo()方法來進行排序,容器中的物件上必須有實作java.lang.Comparable 介面,例如String就有實作java.lang.Comparable介面,結果會使用字典順序來排列容器中的物件。
- 您可以實現自己的排序方式,只要定義一個類別來實作java.util.Comparator介面,例如:
- CustomComparator.java
- package onlyfun.caterpillar;
- import java.util.Comparator;
- public class CustomComparator implements Comparator {
- public int compare(Object o1, Object o2) {
- if (((String) o1).equals(o2))
- return 0;
- return ((Comparable) o1).compareTo(o2) * -1;
- }
- }
- 在自訂的Comparator中,如果兩個物件的順序相同會傳回0,而為了方便比較物件,要求傳入的物件必須實作Comparable介面(例如 String物件就有實作Comparable介面),範例中只是簡單的將原來compareTo()傳回的值乘以負一,如此就可以簡單的讓排列順序相反,接著可以在映射文件中指定自訂的Comparator類別:
- User.hbm.xml
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="onlyfun.caterpillar.User" table="user">
- ....
- <set name="emails" table="email"
- sort="onlyfun.caterpillar.CustomComparator">
- <key column="id"/>
- <element type="java.lang.String"
- column="address"/>
- </set>
- </class>
- </hibernate-mapping>Bag與List並不適用於這種方式。
- 另一個排序的方式則是在資料庫中進行,直接使用order by子句來排序,這可以在映射文件中使用order-by屬性來指定,例如:
- User.hbm.xml
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="onlyfun.caterpillar.User" table="user">
- ....
- <set name="emails" table="email" order-by="address desc">
- <key column="id"/>
- <element type="java.lang.String"
- column="address"/>
- </set>
- </class>
- </hibernate-mapping>觀察Hibernate所使用的SQL可以看到order by子句:
- Hibernate:
- select emails0_.id as id0_, emails0_.address as address0_
- from email emails0_ where emails0_.id=? order by emails0_.address desc
- <PRE class=java name="code"></PRE>
Re: 求助:房东检查我的垃圾要罚款(转寄)
标 题: Re: 求助:房东检查我的垃圾要罚款
发信站: BBS 未名空间站 (Mon Mar 19 00:31:56 2012, 美东)
又一个可怜的孩子呀。
你刚来美国,还是留学生刚来?
不是傻B,就是你的房东变态,这样不合理,也是对你严重侵犯,房东知道你不可能去
找律师告的。
1。房东这样的租住合同是严重侵犯你的,没有这样的苛刻规定你要分开回收东西,全
是扯淡,先看看报纸找律师咨询一下。记住,即使你交了钱一定要收据,一样,我们住
公寓,那有什么回收东西分开,全是仍到一个大垃圾站。
2。 美国都是表演的天才之国度,房东总有失手的时候,在失手的同时也是你解脱之日
,我看到过一个例子,房东喜欢查看你,有your住的钥匙,哪天等你回家,她要是来过
你家,你先跑去问他,你有开门进去的吗?他mybe说我看看有没有虫子什么的,去过,
你事先把有利于你的谈话,录音下来,回去马上打911家里被盗了,3000块昨天下午取
的在银行,这里还有收据。等警察取证是播放你的录音。
3。再找房东就好商量,你这不安全,理由,你看只有你进过我门,还在我不在家的情况
下,你对我的侵犯,等等,我现在就搬家。拿出你事先准备的协议书签名搬家走人。
愚人之见。
--
※ 来源:・WWW 未名空间站 海外: mitbbs.com 中国: mitbbs.cn・[FROM: 72.181.]
2012年3月18日星期日
来BSO一下跟n个CAMRY DEALER战斗的结果(转寄)
标 题: 来BSO一下跟n个CAMRY DEALER战斗的结果
发信站: BBS 未名空间站 (Sun Mar 18 05:20:26 2012, 美东)
这两天跑了5家TOYOTA DEALER,跑之前INTERNET QUOTE了20家,
打印了各种资料和QUOTES有两寸厚,一个大夹子带着信心十足
走入每个DEALERSHIP。另外带着电脑,充电器,水和食物。
进入DEALER店后,先拿出FOLDER有意无意给SALES看,不笑,
一直板着脸严肃状,先直接跟SALES约法三章:
1.我前后只有1个小时时间跟你讨论,没有结果我就走,期间
假装拿出DEALER LIST,打电话给下一家问一个小时后可不可以去。
2.不试驾,不看车,告诉他已经都看好,非常熟悉车的样子。
3.最后定下我满意的成交价前不给任何个人信息,
包括姓名(LAST NAME),家庭地址,公司地址等等,所有跟价格
无关的问题一概不回答,他们爱有啥表有啥表,我就是不填。不给
价格就走人,后来所有SALES都软了。
当然要留电话,以防万一我没谈成价格WALK OUT后,他们有更低价
打电话叫我。事后证明留电话留对了,找到最低OTD就是在我WALK
OUT 3分钟后,被电话叫回去的。
我上来直接给SALES我要的车的SPECIFICS,颜色,配置。我的OPTIONS
全部给CODE,比如PD, P2什么的。就给我BEAT我现在从别人拿到的最
低的OTD,MATCH都不行,一定要BEAT。一旦可以BEAT,我要求DEALER
打印详细OFFER,并且手机照相,因为他们都不会给那张纸的。如果
BEAT成功,OK,现在我就达到目的了,跟SALES说 PLEASE GIVE ME A
SECOND,我就出去打电话给另一下靠谱的DEALER,要求他们电话里面
BEAT我刚从这家拿到的最低价。然后再跑另一家。。。嘿嘿。
这里有个很重要的TIP。DEALER都是受过心里学训练的,我们没有受过
专业训练,容易袒露心理状态。所以一定要经常让SALES离开桌子,尤其
在你考虑他给的一个价格的时候,这个时候最容易暴露你的心里状态,
一定要跟SALES说,CAN YOU GIVE ME A MINUTE HERE, LEAVE ME ALONE,
AND I WILL THINK ABOUT IT。这样屋子或者CUBE只有你一个人对着DEALER
给的OFFER NUMBERS,随便你怎么算计,什么表情,SALES都不知道了,
这样一来,他们受过的训练一点都用不上。
还有一点,当SALES MANAGER出来的时候,他是来试探你的心理的,
一定要少说,而且尽量控制自己的表情,保持前后没有变化。
一个杀手锏:WALK OUT。你在北京秀水街,西单韩国店买过东西吗?如果
你买过,你一定知道WALK OUT的力量。其实这里买车一样。美国人很少有人
突然WALK OUT,所以这是对美国这些傻粗没见过世面的SALES最大最有效的
冲击。他们绝对会挽留你,这个时候你又占上风了。总之一切时候保持
气场压倒对方。WALK OUT没啥,大不了去别的家,大不了以后再回来,
大不了买别的车。我跟这5家DEALER斗的过程中,曾经有一次我都已经签
正式文件了,我选择WALK OUT,他们立刻软了,呵呵,又降价300。
另外谈判期间,我时不时拿出电话假装打电话给另外的DEALER问价格是不是
确定,无数次的挑战号称学过心理学行为学什么乱七八糟学的DEALER
的心理。包括几次他们的GENERAL SALES MANAGER都出来跟我谈,我还是
一直处在谈判上峰,保持极高的气场。
最后实践证明一切DEALER都是纸老虎,最后成交的那家是在我WALK OUT
后叫我回去,由FLEET SALES MANAGER直接跟我谈FLEET的卖价 :)))
好爽的砍价经历啊。有的DEALER的SALES MANAGER都扛不住了,问我谁
会出那么低的OTD,根本不可能做到,我给他看EMAIL,他想看是哪家
DEALER出的价,我直接回绝,说我不能告诉你。他让我DO HIM A FAVOR
告诉他是哪家,以后他们好更好的服务别的顾客。我说,NO, YOU CAN
ASK, BUT I DECLINE TO ANSWER。直接WALK OUT,哈哈哈。SALES MANAGER
说我TOUGH,我说YES YOU GOT IT BUT TOO LATE。
报价吧,最后,大家准备好了。2012 CAMRY SE ALMOST ALL PACKAGES
INCLUDED, MOON ROOF, ENTUNE, ALL LEATHER SEATS, EVERYTHING
INCLUDE $1000 FINANCE REBATE, DRIVE OUT $21,500。好爽!
估计我现在立刻卖掉也是赚钱的,呵呵。天下DEALER都是纸老虎,只要
大家做好功课,保持气场,拿下他们没问题!
--
※ 修改:・SimFan 于 Mar 18 12:53:33 2012 修改本文・[FROM: 173.74.]
※ 来源:・BBS 未名空间站 海外: mitbbs.com 中国: mitbbs.cn・[FROM: 173.74.]
2012年3月15日星期四
[原]Hibernate一对多(单向) - wintysのブログ - BlogJava
[标题]: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