面向对象程序和关系型数据库
闲话    java 数据库    2016-08-28 23:01:45    278    0    0

关系型数据库中存在: 一对一 ,一对多,多对一,多对多 等多种常见关系。程序中的思想是面向对象的,所以程序和数据库对接的地方通常需要使用中间层。太厚的中间层如各种 ORM ,使用方便,但是调整细节困难重重;不用中间层,操作jdbc 过于复杂。所以 Java 这里出现了半自动的工具,比如 Mybatis 。我尝试制作一个更方便的工具,但是困在了 1+N 问题。

Mybatis 做了两件事情,一件是根据变量不同使用模版生成sql ,免除了在程序中拼装 sql 的问题。第二件是完成了查询结果到对象的映射。我很认同第一件,这个思想的来源就跟 html 不再在程序中拼接,而是把控制语句标注在 html 中的想法是一样的。第二件我觉得做的太复杂了,首先需要定义 model ,然后需要在 mapper 中定义接口, Service 接口中声明方法,Service 实现中实现方法。

  • 看到 jfinal 中的做法后,我觉得 model 有时候可以不需要,都用 hashmap代替就好了;后来在使用中发现,一直用 hashmap 容易有拼写错误,不会有代码提示。所以有些时候从数据库反向生成 model 还是很有用的。

  • mapper 我觉得完全没有必要。

  • 从依赖接口而不是依赖实现的角度看,Service 接口和 Service 实现是需要的。但是实际上写起来稍微麻烦了点,通常都是同时改的,而且不能有多个实现,所以小项目我都不写。

目的:比 Mybatis 更简单

参考jfinal 的做法,jfinal 其实轻量的封装了 jdbc,实际使用中存在拼接 sql 不方便的问题,所以我写了一份兼容 Mybatis 语法,但是只包含模版部分的工具库 sqlTemplate

对一

一对一、多对一的结构通常在数据库中就表示就是一个字段,或者一个id 外链。如果写在一个字段,说明这只是一个属性,如果是一个id ,通常说明这个属性是一个稍大的对象。为了方便面向对象的程序处理,我们通常在并表的时候在属性名字前面加上扩展,后期在把他们组合起来。

SELECT
a.id,a.title,a.content,a.createtime,a.updatetime,
category.id as category_id,
category.name as category_name,
FROM article a
LEFT JOIN category on category.id = a.category</pre>

其中属性中的 category_ 让后能够在整理查询结果的时候直接将 category 作为属性,而将 id 和 name 作为 category 的 属性,以后用的时候会非常方便。

对多

一对多的情况就不太好处理了,比如说是 article 和 tags 。

  • 如果使用两条sql 分别查,先把 article 查出来,再去找关联的所有 tag,这样可以,但是如果同时取多个 article,那就需要 1+n 条 sql了,性能上通常是不能接受的。
  • 如果使用 sql并表,一次性查出来部分组,那就要使用程序来分组,同时分页插件什么都就都不能用了。
  • 如果使用 sql并表并分组,那么 tags 只能取到一个。

这就是麻烦的地方,1+n 问题,mybatis 是有解的,但是自己做怎么做呢?我暂时用着一条取巧的办法,使用 GROUP_CONCAT 方法,将 tags 拼成 json,然后程序中解析。这个方法有很多问题:GROUP_CONCAT 是有大小限制的。json 拼接不能有双引号。

SELECT
a.id,a.title,a.seotitle,a.readnum,a.likenum,a.commentnum,a.describe,a.content,a.createtime,a.updatetime,
category.id as category_id,
category.name as category_name,
CONCAT('[',GROUP_CONCAT('{"id":"',tag.id,'","name":"',tag.name,'"}'),']') AS jsonstr_tags
FROM article a
LEFT JOIN article_tag on a.id = article_tag.article
LEFT JOIN tag on tag.id = article_tag.tag
LEFT JOIN category on category.id = a.category
GROUP BY a.id
ORDER BY a.createtime desc</pre>

如果你有关于 1+N 问题的想法,请联系我哦。

文档导航