一对一主键单向引用
User 和car的一对一,car id主键引用user id作为外键。User实体可以访问card实体,但是反之不配置(单向)。
CREATE TABLE `card` (
`id` int(11)NOT NULL ,
`info`varchar(255) DEFAULT NULL,
PRIMARY KEY(`id`),
UNIQUE KEY`id` (`id`) USING HASH,
CONSTRAINT`card_ibfk_1` FOREIGN KEY (`id`) REFERENCES `user` (`id`) ON DELETE CASCADE ONUPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
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;
Card
publicclassCard implements Serializable {
privateInteger id;
private String info;
User
publicclassUser implements Serializable {
privateInteger id;
privateString name;
privateInteger age;
private Card card;
mapping配置表
<class
name="org.hibernate.tutorial.domain.Card"
table="card"
>
<id
name="id"
type="java.lang.Integer"
column="id"
>
<generator class="assigned"/>
<!-- <generatorclass="native" /> -->
</id>
<property
name="info"
type="java.lang.String"
column="info"
length="255"
/>
<class
name="org.hibernate.tutorial.domain.User"
table="user"
>
<id
name="id"
type="java.lang.Integer"
column="id"
>
<generator class="native"/>
</id>
<property
name="name"
type="java.lang.String"
column="NAME"
length="20"
/>
<property
name="age"
type="java.lang.Integer"
column="age"
length="10"
/>
<one-to-one name="card"class="org.hibernate.tutorial.domain.Card"cascade="all"/>
测试
@Test
/**
* 一对一主键单向关联
*/
publicvoid testOnetoOneOneWay() {
// 读取hibernate.cfg.xml文件
Configurationcfg= newConfiguration().configure();
// 建立SessionFactory
SessionFactoryfactory= cfg.buildSessionFactory();
// 取得session
Sessionsession= null;
try {
session = factory.openSession();
// 开启事务
session.beginTransaction();
Useruser= newUser();
user.setName("Lucy13");
user.setAge(19);
session.save(user);
Cardcard= newCard();
card.setInfo("card");
//如果这一句注释掉,插入将会失败,因为在mapping中配置了assigned,必须人工设置
card.setId(user.getId());
user.setCard(card);
session.save(user);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
// 回滚事务
session.getTransaction().rollback();
}finally{
if (session != null) {
if (session.isOpen()) {
// 关闭session
session.close();
}
}
}
}
配置一对一主键单向关联的时候,外键在Card中,但是关联关系配置在User中。在测试代码中如果这句代码注释掉,会报错card.setId(user.getId());即使把配置中的generator配置为native也是会失败的。即使在之前先save(card)。
我猜大概是hibernate底层封装的时候的问题。先看下正常的插入产生的sql语句
……
session.save(user);
……
user.setCard(card);
session.save(user);
Hibernate: insert into user (NAME,age) values (?, ?)
Hibernate: select card_.id,card_.info as info2_ from card card_ where card_.id=?
Hibernate: insert into card (info,id) values (?, ?)
1、 插入user,id式自增长的
2、 配置一对一user中的card,由于同时配置了cascade=”all”,所以会在更新user是同时更新card,由于card是新建的实体,查不到然后会自动插入。
而以下的保存方式就只有两条sql语句
……
session.save(user);
……
session.save(card);
user.setCard(card);
session.save(user);
Hibernate: insert into user (NAME,age) values (?, ?)
Hibernate: insert into card (info,id) values (?, ?)
另外为什么cardid的generator配置为native,让数据库自动判断就不行了呢?大概是一对一关系配置在user中,插入card的hibernate无法知道card对应得user实体是哪个,变无法判断cardid。(既使给id加上自增长的属性,也是不行的。大概cardid引用了userid作为外键,自增长的id可能无法满足这个约束)这里我还没理清楚,暂时先搞搞配置