nhsoft_yhw 2009-08-21 18:31
浏览 265
已采纳

hibernate 多表 join 查询发现还是会重新load one-to-many 子表

原来的系统性能慢,今天在做性能调优,发现有一个多表查询存在性能问题。

我的hbm.xml配置文件
[code="java"]












[/code]

查询语句:

   [code="java"] Criteria criteria = getSession().createCriteria(Shop.class, "s")
            .createAlias("s.shopHours", "h", JoinFragment.LEFT_OUTER_JOIN)
            .createAlias("s.shopRate", "r", JoinFragment.LEFT_OUTER_JOIN)
            .createAlias("s.shopConditions", "c", JoinFragment.LEFT_OUTER_JOIN)
            .add(Restrictions.eq("s.shopCity", cityName))
            .add(Restrictions.eq("s.shopActived", true))
            .add(Restrictions.eq("s.shopPublic", true))
            .addOrder(Order.asc("s.shopNum"))
            .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    return criteria.list();[/code]

调试中的sql 日志:
[code="java"]
Hibernate: /* load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions / select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?
Hibernate: /
load wm.model.ShopRate / select shoprate0_.shop_num as shop1_36_0_, shoprate0_.taste_rating as taste2_36_0_, shoprate0_.service_rating as service3_36_0_, shoprate0_.response_rating as response4_36_0_, shoprate0_.total_rating as total5_36_0_, shoprate0_.reviews_count as reviews6_36_0_ from shop_rate shoprate0_ where shoprate0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopHours / select shophours0_.shop_num as shop2_1_, shophours0_.shop_hour_id as shop1_1_, shophours0_.shop_hour_id as shop1_23_0_, shophours0_.shop_num as shop2_23_0_, shophours0_.time_from as time3_23_0_, shophours0_.time_to as time4_23_0_ from shop_hour shophours0_ where shophours0_.shop_num=?
Hibernate: /
load one-to-many wm.model.Shop.shopConditions */ select shopcondit0_.shop_num as shop2_1_, shopcondit0_.condition_id as condition1_1_, shopcondit0_.condition_id as condition1_37_0_, shopcondit0_.shop_num as shop2_37_0_, shopcondit0_.condition_mile as condition3_37_0_, shopcondit0_.condition_money as condition4_37_0_, shopcondit0_.condition_amount as condition5_37_0_, shopcondit0_.condition_response_time as condition6_37_0_ from shop_condition shopcondit0_ where shopcondit0_.shop_num=?[/code]

从上述日志,我发现hibernate join查询后,还是重新做了select查询,调试了半天,没有什么眉目,希望有高人指导,谢谢!

补充:
两个与查询有关的配置参数
hibernate.max_fetch_depth 3
hibernate.default_batch_fetch_size 8
[b]问题补充:[/b]
fetch 方式 select,subselect,join均试过,打印出来的sql语句相同,均存在n+1查询问题。

另外,一对多是可空的,即多的一端可以有一个或多个,也可以不存在。

另外,在创建critia时,已经设定了以做左连接方式join查询(JoinFragment.LEFT_OUTER_JOIN),应该来说会覆盖hbm配置文件中的设定。

[b]问题补充:[/b]
现在的我的使用场景中,必须设置lazy=false,否则代码调整量比较大的。
[b]问题补充:[/b]
我的问题主要有一个疑惑:从上述SQL语句中我们发现,hibernate确实已经使用了join方式查询,为什么还需要重新select呢?

  • 写回答

8条回答 默认 最新

  • iteye_7589 2009-08-25 12:57
    关注

    [quote]问题补充:
    我的问题主要有一个疑惑:从上述SQL语句中我们发现,hibernate确实已经使用了join方式查询,为什么还需要重新select呢?[/quote]

    这个已经很说明问题了。 就是说hql里用的join得到对象用的行映射,并不是关联映射。
    就是说当你访问shop.getShopConditions()时,是用shop对象的关系去取 shopCondition
    而不是你的hql里行关联的ShopConditions

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(7条)

报告相同问题?

悬赏问题

  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型