2

用到许多数据库关系化映射中间件,hibernate,jpa,iBATIS,最近研究nodejs,发现一款不可多得的orm开源工具sequelize,支持promise,映射配置/查询/数据输出等都是json格式,非常顺心,官方文档很标准但完全说不透其强大的功能,很多都需要实际用到才能体会,就像json一样变化多端,你猜不透它有多少种变化。

好,下面来看一个需求案例:
一条这样的普通查询语句:

select * from product join producton product.id=place.productid and place.city=1100 where product.price>100 limit 10

用sequelize的query来写,如果写成这样:

models.product.findAll({
    where: ["price>=?", 100 ],
    include: [{
        model:models.product,
        where: { city:1100 }
    }],
    limit:12
})

实际上运行的sql是这个:

select product.*, place.* from (select * from product where product.price>100 limit 10) join place on product.id=place.productid and place.city=1100

想要的结果是错误的,分页时没有把city:1100 条件限制了,结果有差异,那怎么办?

于是找方法,看到有人使用加subQuery:false条件来处理,如下:

models.product.findAll({
    where: ["price>=?", 100 ],
    include: [{
        model:models.product,
        where: { city:1100 }
    }],
    limit:10,
    subQuery:false   //不让在子查询里分页,全局处理
})

这样对于只含一个include关联的查询倒是问题不大,如果include多个对象,关联的对象有1对多,多对多的关系,就不好控制了。

我的解决方法是,在需要一对一关联的表中加入required:true,这样就会将这个条件放在分页之前执行,

models.product.findAll({
    where: ["price>=?", 100 ],
    include: [{
        model:models.product,
        where: { city:1100 },
        required:true  //inner join方式
    }],
    limit:10,
})

运行时sql如下:

select product.*,place.* from product join place on product.id=place.productid and place.city=1100 where product.price>100 limit 10

required参数一般是指关联对象是外联还是内联,内联required=true可以表示内联条件优先,分页在后。
以上内容进仅供参考,使用场景不同,理解也不一样。


微笑浆糊
2 声望0 粉丝

it老戏骨,能看穿代码,看不透人生,自得其乐,足矣