对比 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)
9344 次点击
所在节点    Java
103 条回复
cheng6563
2020-12-11 17:39:03 +08:00
@Braisdom 我火星了吗 Java 哪来的运算符重载
taogen
2020-12-11 17:44:21 +08:00
试着对比一下这个 sql 呢?下面是 mybatis 写法

SELECT name, value
FROM (
SELECT b.site AS name, COUNT(*) AS value
FROM task AS a
left join task_for_development AS b ON b.task_id=a.id
WHERE a.delete_flag=FALSE AND a.category="development" AND b.site IS NOT NULL AND b.site != ''
<trim prefix="and" suffixOverrides="and">
<if test="beginTime != null">
DATE(a.create_time) <![CDATA[ >= ]]> #{beginTime,jdbcType=TIMESTAMP} and
</if>
<if test="endTime != null">
DATE(a.create_time) <![CDATA[ <= ]]> #{endTime,jdbcType=TIMESTAMP} and
</if>
</trim>
GROUP BY b.site
) AS temp2
ORDER BY value desc limit 10
ychost
2020-12-11 17:51:07 +08:00
看着和 tk.mybatis 一样呢,另外 JPA 的 SpecificationExecutor 和 Example 用起来也很简单,不过还是喜欢 .NET 的 LINQ 感觉这才是最好用的
Ayanokouji
2020-12-11 17:53:23 +08:00
和 ebean jooq 比有啥优势( jooq 非开源的收费)
qwerthhusn
2020-12-11 17:57:09 +08:00
'%#{title}%' 这样如果没校验,分分钟 SQL 注入
lishen226
2020-12-11 18:33:54 +08:00
sql 可读性更强些
Kirsk
2020-12-11 19:12:45 +08:00
@Braisdom 设计的挺好的 不过条件查询上是怎样个用法 看起来有点接近 sql 拼接了 应该可以用下 example spec 的思路 example 没实现条件表达
miao1007
2020-12-11 20:40:18 +08:00
这个人员流动大时,控制不住质量
VeryZero
2020-12-11 21:00:57 +08:00
支持一下,不过看着跟 JPA 类似啊,有什么这个能做,JPA 不能做的特性吗?
Braisdom
2020-12-11 21:07:40 +08:00
@cheng6563 看我的代码,我实现了运算符重载


@taogen 你想要的通过这种方式很容易实现

Member.Table member = Member.asTable();
Order.Table order = Order.asTable();

Select select = new Select();

select.project(member.no, member.name, count().as("order_count"))
.from(member)
.leftOuterJoin(order, order.memberId.eq(member.id))
.groupBy(member.no, member.name);

List<Member> members = select.execute(Member.class);
Braisdom
2020-12-11 21:09:20 +08:00
@VeryZero 下面的复杂表达式计算,现有的所有 ORM 框架都做不到,但却很实用。

```
Order.Table orderTable = Order.asTable();
Select select = new Select();

select.project((sum(orderTable.amount) / sum(orderTable.quantity) * 100).as("unit_amount"))
.from(orderTable)
.where(orderTable.quantity > 30 &&
orderTable.salesAt.between("2020-05-01 00:00:00", "2020-05-02 23:59:59"))
.groupBy(orderTable.memberId);

List<Order> orders = select.execute(Order.class);

```
adguy
2020-12-11 21:51:03 +08:00
手写 sql 是对我这个 crud 仔最后的尊重
Braisdom
2020-12-11 21:54:26 +08:00
@adguy 哈哈,可能我要把基础的 CRUD 变为 Java API 了
kylix
2020-12-11 22:44:38 +08:00
恕我眼拙,没看出来
sprite82
2020-12-11 22:47:52 +08:00
很好,可我还是选择 mybatis plus
Jrue0011
2020-12-11 22:48:47 +08:00
那如果需要使用一些函数比如 Oracle 的 partition by 呢,毕竟框架如果没提供,要么就直接写 SQL,要么就只能通过框架的扩展能力自己实现,这样想想还是写 SQL 好维护一些。
rockyou12
2020-12-11 23:26:46 +08:00
你这实现的……我用 jpa+querydsl 都完全能做啊,优势在哪……
casillasyi
2020-12-11 23:38:39 +08:00
mybatis 和 jpa 的优势在于,开发者知道自己最终的 sql 是什么
zmxnv123
2020-12-11 23:38:42 +08:00
可惜我用 SqlAlchemy
nc4697
2020-12-11 23:46:50 +08:00
看起来 MyBatisPlus 更易用。但是也说明楼主的项目潜力还是很大,加油

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

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

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

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

© 2021 V2EX