One-to-many,进行配置一对多外键关联
User 和cards的一对多,cards id主键,自增长,属性uid引用user id作为外键。User实体可以访问cards实体集,但是反之不行(单向)。官方不推荐。
CREATE TABLE `cards` (
`cid` int(11)NOT NULL AUTO_INCREMENT,
`uid` int(11),
`info`varchar(255) DEFAULT NULL,
PRIMARY KEY(`cid`),
KEY `uid`(`uid`) USING BTREE,
CONSTRAINT`cards_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE CASCADEON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8ROW_FORMAT=COMPACT;
CREATE TABLE `user` (
`id` int(11)NOT NULL AUTO_INCREMENT,
`name`varchar(50) NOT NULL,
`age` int(50)NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULTCHARSET=utf8;
publicclassUser implements Serializable {
privateInteger id;
privateString name;
privateInteger age;
private Set cards;
publicclassCards implements Serializable {
privateInteger cid;
privateString info;
private Integer uid;
User.hbm.xml
<set name="cards" lazy="true"inverse="false" cascade="all">
<key>
<column name="uid"/>
</key>
<one-to-many class="org.hibernate.tutorial.domain.Cards"/>
</set>
Cards.hbm.xml
<class name="org.hibernate.tutorial.domain.Cards"table="cards">
<id name="cid" type="java.lang.Integer"column="cid">
<generator class="native"/>
</id>
<property name="uid"type="java.lang.Integer" column="uid"/>
<property name="info"type="java.lang.String" column="info" length="255"/>
</class>
测试
@Test
publicvoid testonetomanyOneWay() {
// 读取hibernate.cfg.xml文件
Configurationcfg= newConfiguration().configure();
// 建立SessionFactory
SessionFactoryfactory= cfg.buildSessionFactory();
// 取得session
Sessionsession= null;
try {
session = factory.openSession();
// 开启事务
session.beginTransaction();
Useru1 = (User) session.load(User.class, new Integer(16));
Cardscard= newCards();
card.setInfo("welcome");
u1.getCards().add(card);//设置一对多
session.save(u1);//插入user,会自动添加card纪录
System.err.println(u1.getCards().size());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
// 回滚事务
session.getTransaction().rollback();
}finally{
if (session != null) {
if (session.isOpen()) {
// 关闭session
session.close();
}
}
}
}
更新user的时候,产生以下sql语句
Card表,uid允许为空,另外Cards.hbm.xml中uid也没有配置(忘记了)
session.save(u1)
Hibernate: select user0_.id asid0_1_, user0_.NAME as NAME0_1_, user0_.age as age0_1_, card1_.id as id2_0_,card1_.info as info2_0_ from user user0_ left outer join card card1_ onuser0_.id=card1_.id where user0_.id=?
Hibernate: select cards0_.uid as uid1_,cards0_.cid as cid1_, cards0_.cid as cid1_0_, cards0_.info as info1_0_ fromcards cards0_ where cards0_.uid=?
Hibernate: insert into cards (info) values (?)
Hibernate: update cards set uid=?where cid=?
session.save(card)
Hibernate: select user0_.id asid0_1_, user0_.NAME as NAME0_1_, user0_.age as age0_1_, card1_.id as id2_0_,card1_.info as info2_0_ from user user0_ left outer join card card1_ onuser0_.id=card1_.id where user0_.id=?
Hibernate: select cards0_.uid asuid1_, cards0_.cid as cid1_, cards0_.cid as cid1_0_, cards0_.info as info1_0_from cards cards0_ where cards0_.uid=?
Hibernate: insert into cards (info)values (?)
Hibernate: update cards set uid=?where cid=?
进一步Cards.hbm.xml中uid配置
<property name="uid"type="java.lang.Integer" column="uid"/>但是uid还是允许为空
session.save(u1)
Hibernate: select user0_.id asid0_1_, user0_.NAME as NAME0_1_, user0_.age as age0_1_, card1_.id as id2_0_,card1_.info as info2_0_ from user user0_ left outer join card card1_ onuser0_.id=card1_.id where user0_.id=?
Hibernate: select cards0_.uid asuid1_, cards0_.cid as cid1_, cards0_.cid as cid1_0_, cards0_.uid as uid1_0_,cards0_.info as info1_0_ from cards cards0_ where cards0_.uid=?
Hibernate: insert into cards (uid, info) values (?, ?)
Hibernate: update cards set uid=?where cid=?
session.save(card)
Hibernate: select user0_.id asid0_1_, user0_.NAME as NAME0_1_, user0_.age as age0_1_, card1_.id as id2_0_,card1_.info as info2_0_ from user user0_ left outer join card card1_ onuser0_.id=card1_.id where user0_.id=?
Hibernate: select cards0_.uid asuid1_, cards0_.cid as cid1_, cards0_.cid as cid1_0_, cards0_.uid as uid1_0_,cards0_.info as info1_0_ from cards cards0_ where cards0_.uid=?
Hibernate: insert into cards (uid, info) values (?, ?)
Hibernate: update cards set uid=?where cid=?
两次插入cards应该都是uid=null
然后将cards的uid设置为不允许为空,那么上面的插入就会失败,大概是一个Column'uid' cannot be null。代码中需要手动配置card.setUid(user.getId());
我猜测大概是hibernate的策略是先插入外键空值,然后更新外键set uid=? where cid=?。
有个问题,按理应该不配置card.setUid(user.getId());也可以保存成功吧,user实例维护一对多的关系,然后插入cards的时候将uid配置。即使说不能为空,我随意设置一个满足约束条件的值(非正确对应的),然后hibernate应该更新对应的uid,但是实际测试貌似没有。
User的id为16,card.setUid(19); user.setCards(cards);插入的cards记录的uid仍然是19.hibernate版本是3.1.觉得有些奇怪