有些困惑,大家帮忙看看一对多映射时save的一个问题,多谢了!!!

aiyu33 2008-12-08 04:01:19
我是在初学hibernate,是仿照书上的例子。我新建了下面两个关联的数据表。create table CUSTOMERS ( ID bigint not null, NAME varchar(15), AGE int, primary key (ID));
create table ORDERS ( ID bigint not null, ORDER_NUMBER varchar(15), PRICE double precision,
CUSTOMER_ID bigint, primary key (ID));
alter table ORDERS add index IDX_CUSTOMER(CUSTOMER_ID),
add constraint FK_CUSTOMER foreign key (CUSTOMER_ID) references CUSTOMERS (ID);
建立了下列hbm.xml
<hibernate-mapping package="com.zl.model">
<class name="Customers" table="customers" >
。。。。
<set name="orderses" lazy="true" cascade="all" inverse="true">
<key>
<column name="CUSTOMER_ID" not-null="true" />
</key>
<one-to-many class="Orders" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping package="com.zl.model">
<class name="Orders" table="orders" >
<many-to-one name="customers" class="Customers" >
<column name="CUSTOMER_ID" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
打开show-sql配置,然后调用下列代码,来测试
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Customers cust = (Customers)session.get(Customers.class, new Long(2));
Orders order = new Orders();
order.setId(4L);
order.setCustomers(cust);
order.setOrderNumber("zl000004");
cust.getOrderses().add(order);
Transaction tran = session.beginTransaction();
System.out.println("before save!");
session.save(cust);
System.out.println("after save!");
tran.commit();
}
按书上的说法,在tran.commit()时,hibernate只调用一条insert order的语句。
但我发现在调用session.save(cust)时,hibernate并没有调用sql语句。但在tran.commit()时,先执行了一条
select orders_.ID, 。。。。from orders orders_ where orders_.ID=4
再执行insert into orders ...sql语句的。但我看的所有hibernate的书上都没有提到会执行这个select语句的。
那这样执行程序时,效率不就很低了?
我要是执行session.save(order)的话,那就只有一条sql语句。
现在就有些疑惑,为什么书上的例子很多都这样写。请过来人给解惑下,多谢了

...全文
97 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
dreamhunter_lan 2008-12-08
  • 打赏
  • 举报
回复
不好意思,好像看错题了,当我没来过
[Quote=引用 4 楼 dreamhunter_lan 的回复:]
第一、你用到了get嘛肯定就马上发出一条select了,要是用load的话就要到order.setCustomers(cust); 以后才会
发出sql,因为load支持lazy(也就是真正用到的时候才会发),一般情况下让lazy默认为true就好,性能会
好些,hibernate3特地做的改进
第二、hibernate在底层是做了优化的,并不一定在save之后就马上发出sql,hibernate先放在缓存了,到最后
再一次进行提交,想要看到发出sql还可以调用flush()方法
[/Quote]
Landor2004 2008-12-08
  • 打赏
  • 举报
回复
书上有没有先不说(可能是漏掉了吧,呵呵)
其实很简单,当子类(Orders)要进行保存操作的时候,要先到数据库里面去查询是否已经存在了,如果存在了就调用update,否则就是insert,这就产生了那条select
楼主是一条Orders,如果是多条的话,就会产生多个sql语句
也不能说影响性能,正常些jdbc的时候也需要这么判断的

如果楼主想去掉这个查询语句,那只有麻烦点了,就是去掉<set name="orderses" lazy="true" cascade="all" inverse="true"> 中的cascade="all"
变为<set name="orderses" lazy="true" inverse="true">,默认的cascade是null的
然后手工保存子类(Orders),比如:
session.save(cust)
session.save(orders1)
session.save(orders2)
一对多余的sql了,但是增加了代码的工作量
dreamhunter_lan 2008-12-08
  • 打赏
  • 举报
回复
第一、你用到了get嘛肯定就马上发出一条select了,要是用load的话就要到order.setCustomers(cust); 以后才会
发出sql,因为load支持lazy(也就是真正用到的时候才会发),一般情况下让lazy默认为true就好,性能会
好些,hibernate3特地做的改进
第二、hibernate在底层是做了优化的,并不一定在save之后就马上发出sql,hibernate先放在缓存了,到最后
再一次进行提交,想要看到发出sql还可以调用flush()方法
fuyueyue 2008-12-08
  • 打赏
  • 举报
回复
学习
zou_wei_forever 2008-12-08
  • 打赏
  • 举报
回复
你的主键是自己指定的,如果你将主键生成方式设置为自增长或者uuid等自动的方式,就不会有那条select语句了
wj_18 2008-12-08
  • 打赏
  • 举报
回复
hibernate 的lazy 特性

3.2以后吧好像,反正前面版本跟现在不一样,新的版本,lazy特性都是开着的
lazy的作用就是懒操作,就是你真正用到那个对象的时候才会执行语句

如果LZ不想用,可以在例如你的

<set name="orderses" lazy="true" cascade="all"  inverse="true"> 


的lazy="true" 改为false

提醒下,注意hibernate的版本

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧