对比 MyBatis,你看出什么端倪?

2020-12-11 16:34:54 +08:00
 Braisdom

项目地址: https://github.com/braisdom/ObjectiveSql

1 简单查询

@DomainModel
public class Blog {
    private Long id;
    private String title;
    private Integer state;
    @Relation(relationType = RelationType.BELONGS_TO)
    private Author author;
}

根据单字段查询

MyBatis ObjectiveSQL
public interface BlogMapper {
  @Select("SELECT * FROM blog WHERE id = #{id}")
  Blog selectBlog(int id);
}
...
BlogMapper mapper = session.getMapper(BlogMapper.class); 
Blog blog = mapper.selectBlog(i);
Blog blog = Blog.queryByPrimaryKey(1);

稍微复杂一点的查询

MyBatis ObjectiveSQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="findByTitle" resultType="Blog">
    select * from Blog where title like  '%#{title}%'
  </select>
</mapper>
...
BlogMapper mapper = session.getMapper(BlogMapper.class); 
Blog blog = mapper.findByTitle("标题");
public static Blog queryByTitle(String title) {
     Query<Blog> query = createQuery();
     query.where("title like ?",  "%" + title + "%");
     return query.queryFirst();
}
...
Blog blog = Blog.queryByTitle(1);

2 复杂查询

动态查询

MyBatis ObjectiveSQL
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE
  <if test="state != null">
    state > #{state}
  </if>
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
...
BlogMapper mapper = session.getMapper(BlogMapper.class); 
Blog blog = mapper.findActiveBlogLike(...);
Blog.Table blog = Blog.asTable();
Select select = new Select();
LogicalExpression eternalExpression = new EternalExpression();
if(state != null)
     eternalExpression = eternalExpression.and(blog.state > state);
if(title != null)
     eternalExpression = eternalExpression.and(blog.title.like(title));
if(author != null && author.name != null)
     eternalExpression = eternalExpression.and(blog.author.like(author.name));
return select.from(blog).where(eternalExpression).execute();

关联查询

MyBatis ObjectiveSQL
<mapper>
  <resultMap type="Blog" id="blog">
    <id column="id" property="id" />
    ...
    <association property="author" javaType="Author">
      ...
    </association>
  </resultMap>
  <select id="findBlog" parameterType="int" resultMap="blog">
    ...
  </select>
</mapper>
...
BlogMapper mapper = session.getMapper(BlogMapper.class); 
Blog blog = mapper. findBlog(...);
Blog blog = Blog.queryByPrimaryKey(1, 
                    Blog.BELONGS_TO_AUTHOR)
9379 次点击
所在节点    Java
103 条回复
murmur
2020-12-11 23:53:04 +08:00
mybatis 的特点就是可以完全控制 sql,尤其是做复杂报表特别好使
zsl199512101234
2020-12-12 00:10:42 +08:00
https://mybatis.org/mybatis-dynamic-sql/docs/quickStart.html
感觉官方的这个更香,打算新项目试一试这个框架
sagaxu
2020-12-12 00:14:06 +08:00
拿 dsl 拼 sql ?我还不如手写 sql,代码量差不多,是个后端就能秒上手,不用学。
micean
2020-12-12 05:54:06 +08:00
楼主最近推广很密集哇
其实现在 idea 做的已经很好了,连上数据库就能用脚本生成一切,写 sql 用 language inject 就可以用上自动完成字段了,还带校验的
重载操作符确实是亮点,但是对于 dsl 写 sql 来说还不够
Braisdom
2020-12-12 09:21:23 +08:00
一个时代的发展前期,总是充满质疑,很正常,等真相大白的一天,各位可以反思一下今天的质疑。
我对比过现有的所有 ORM 框架,才决定做 ObjectiveSQL,以我 15 年编程的经验对比了各种优缺点。

我是做零售系统的大数据分析的,零售业也是最早将数据应用到生产过程中的行业之一,其中的 SQL 与 Java 之间磨合了很多年。我也在其中痛苦了很年。感谢各位支持,你们的质疑也是对我分析优缺点的补充。


@micean
@sagaxu
@zsl199512101234
@nc4697
@casillasyi
@rockyou12
@sprite82
@kylix
Braisdom
2020-12-12 09:22:04 +08:00
@micean idea 做的是不错,但需求是无限增长的
Braisdom
2020-12-12 09:26:08 +08:00
@micean 推广的积极,也就说明项目的成熟度在提升,需要兄弟们支持,需要各位通过实际的行动进行投票。就像优秀的企业是靠客户的钞票投票,而不同情,一味的寻求国产支持,一直靠扶的项目或公司走不远。
justin2018
2020-12-12 10:06:04 +08:00
![WFq6nZv]( )

v2 显示 bug 嘛?
Braisdom
2020-12-12 10:14:26 +08:00
@justin2018 感觉是的,但我的用法不太对呀。应该通过滚动条的。哈哈
xiangyuecn
2020-12-12 10:29:35 +08:00
@qwerthhusn #25 用了这种框架的基本上不存在 sql 注入的问题,#格式是参数化查询( like 字符串虽然也是个表达式,但只是模式而已),除非不明白机制的前提下手贱用$

jdbc 手写参数化查询太麻烦,因此直接拼接 sql 字符串多简单😂 要是易用大部分项目也就没这些要写 xml 的框架什么鸟事了(没错就是那些连接池都用不上的项目)
zsl199512101234
2020-12-12 12:06:31 +08:00
@Braisdom 有你这样的心态和实力,肯定会成功,我会持续关注的
wg20080215
2020-12-12 12:49:05 +08:00
看起来很优秀,可能业务没那么复杂需要 DSL 和 SQL 嵌套着来,我还是继续用 JPA 。
Braisdom
2020-12-12 13:17:58 +08:00
@wg20080215 ObjectiveSQL 有长的长处,也有其短处,不可能覆盖所有场景的使用

JPA 代表的是一种编程模式,以动态代理的编程,ObjectiveSQL 则是以另一种静态生成代码的形式,属于另一个流派,有人喜欢,有人讨厌,这是个人偏好问题。用心做好自己的事,不断进步。
WhereverYouGo
2020-12-12 13:33:52 +08:00
@qmzhixu #5 +1
tydl
2020-12-12 13:36:52 +08:00
比起 php 落后 写这么多代码
Braisdom
2020-12-12 13:43:16 +08:00
@tydl 好问题,每个语言优秀的地方都是可以借鉴的。
Braisdom
2020-12-12 13:44:47 +08:00
@sweetsorrow211 @qmzhixu 有兴趣,可以深入聊一下两者,MyBatis MyBatis-Plus 我用了好多年的,正是因为它们有太做做的不好的地方,我才开始 ObjectiveSQL 项目的。
hantsy
2020-12-12 13:49:31 +08:00
10 多年没接触 Batis,实在没法比较,自进入 Apache 就没用过了,后来又被 Apache 踢出去了。

>下面的复杂表达式计算,现有的所有 ORM 框架都做不到,但却很实用。

这个吹得有点过了。

如果与 JPA 比较,从 Type Safe 角度考虑, 我首选用 JPA Criteria API ( Criteria 操作可似代替复杂的 JPQL ),不用 Spring Data 的话,自己写个通用接口,https://github.com/hantsy/helidon-sample/blob/master/mp-jpa/src/main/java/com/example/Repository.java 复杂的自己定义一下 Criteria Predicate 。

从软件设计的角度,Domain 为中心已经不再关心 Table 了,SQL 还是 NoSQL 。
Braisdom
2020-12-12 13:57:09 +08:00
@hantsy 现有的框架当然支持复杂表达式了,只不过支持的方式不同而已,
以同环比的投影表达式为例:
SQL:(sum(t1.current) - sum(t1.last)) / sum(t1.last) * 100
ObjectiveSQL: (sum(sales.current) - sum(sales.last)) / sum(sales.last) * 100

// sales 为 Order.asTable() 方法生成,该方法包括内部的所有字段均为怎么生成

我的项目几乎和 SQL 一模一样,你猜其它项目会怎么做呢?字符?还是 lambda
Braisdom
2020-12-12 14:05:17 +08:00
@hantsy 除了这些比较简单的表达式,下面的表达式呢?

过滤:where (t1.amount > 1000 and t1.product_code = '0001') and (t1.state = 1 or t1.state = null)

ObjectiveSQL: order.where((order.amount > 1000 && order.product_code.eq('0001'))
&& order.state.eq(1) || order.state.isNull() )

您是大佬,能看出我的 API 设计吗?为什么要做这件事,其它的 ORM 框架对于上述表达式什么怎么做?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/734572

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX