Mybatis 到底是或不是 ORM?为什么?

2023-11-23 06:16:26 +08:00
 mangojiji
我觉得它是,因为它确实可以将对象保存到数据库也可以从数据库里检索到对象,
但隐约感觉哪里好像又有点不对劲。。

它和 hibernate 以及 ebean 之流的框架到底谁是 ORM ,如它不是 ORM ,那么究竟是缺失了什么特征呢?
3913 次点击
所在节点    数据库
35 条回复
zhazi
2023-11-23 15:06:00 +08:00
虚空打靶呢?
@burymme11
shyangs
2023-11-23 15:42:37 +08:00
@burymme11
@totoro52

XML 沒有 Java 語法級別的提示和靜態語言重構輔助.

新增欄位?就搜尋關鍵字然後一行一行改 XML 吧,一不小心就改錯了或漏了.(我相信任何用過 MyBatis 的人都遇到過這個問題)
thinkershare
2023-11-23 15:55:21 +08:00
你如果.NET 的 ORM 框架,立马就能理解 ORM 和各种 SQL Helper 的差别。同意楼上的,自定义 DSL 的都是狗屎。
songteng0604
2023-11-23 18:32:40 +08:00
//来自 B 站尚硅谷 SSM 课程 https://www.bilibili.com/video/BV1AP411s7D7?p=98

ORM ( Object-Relational Mapping ,对象-关系映射)是一种将数据库和面向对象编程语言中的对象之间进行转换的技术。它将对象和关系数据库的概念进行映射,最后我们就可以通过方法调用进行数据库操作!!

mybatis 是半自动 orm 思维的持久层框架(提供 crud 的方法,不提供 sql 语句),hibernate 是全自动 orm 框架(数据库数据和 Java 实体类的映射可以通过配置直接实现,最终提供 crud 的方法和自动生成对应的 sql 语句),但 hibernate 被淘汰了。

将来开发中使用的是 mybatis-plus 。它是从半自动到全自动的过度,提供了单表 curd 的方法。
ZZ74
2023-11-23 18:43:52 +08:00
作为一个 CURDer ,你永远不知道查询条件会有多奇葩,所以我选择 ibatis 这类,碰到复杂能手写 sql ,简单还高效。简单场景 写过的几乎都能复用。
tzengshinfu
2023-11-23 18:58:28 +08:00
gowk
2023-11-23 19:02:52 +08:00
DSL 纯粹是多此一举,失去了 SQL 的灵活,又增加了认知负担,得不偿失,SQL builder 或者 ORM 专注自己的领域就好了,do one thing and do it well ,Mybatis 真的就是一个 Mapper 而已,用起来还不错,就是业务逻辑复杂改起来就很啰嗦,Gorm ent 之流也能凑合用,但是都没有 EF ,Active Record ,Eloquent ,还有 node 世界的某些好用。真的感慨 Java 世界竟然没有一个顺手的 ORM ,JPA 太重,不灵活,也可能是我菜,所以干脆连笨重啰嗦的 Java 一并抛弃,拥抱 .NET ,EF 自不必说,甚至连国产的 SqlSugar 都可圈可点,用起来很舒服。

查询语法:
var exp = Expressionable.Create<Supplier, SysUser>();
exp.AndIF(dto.SupName.IsNotEmpty(), (t, u) => t.SupName.Contains(dto.SupName));
exp.AndIF(dto.CreditCode.IsNotEmpty(), (t, u) => t.CreditCode.Contains(dto.CreditCode));
exp.AndIF(dto.Address.IsNotEmpty(), (t, u) => t.Address.Contains(dto.Address));
exp.AndIF(dto.DetailAdmissionType.IsNotEmpty(), (t, u) => t.DetailAdmissionType.Contains(dto.DetailAdmissionType));
exp.AndIF(dto.Leader.IsNotEmpty(), (t, u) => t.Leader.Contains(dto.Leader));
exp.AndIF(dto.AdmissionTerm.HasValue, (t, u) => (int)t.AdmissionTerm == dto.AdmissionTerm);
exp.AndIF(dto.StartNumber.HasValue, (t, u) => t.RegCapitalSubscribed >= dto.StartNumber);
exp.AndIF(dto.EndNumber.HasValue, (t, u) => t.RegCapitalSubscribed <= dto.EndNumber);
exp.AndIF(dto.DeptId.HasValue, (t, u) => u.DeptId == dto.DeptId);
exp.AndIF(dto.AdmissionType.HasValue, (t, u) => t.AdmissionType == dto.AdmissionType);
exp.AndIF(dto.CompanyType.HasValue, (t, u) => t.CompanyType == dto.CompanyType);
exp.AndIF(dto.BeginTime.HasValue, (t, u) => t.CreateTime >= dto.BeginTime);
exp.AndIF(dto.EndTime.HasValue, (t, u) => t.CreateTime <= dto.EndTime);

var result = _supplierService.Queryable()
.InnerJoin<SysUser>((t, u) => t.CreateBy == u.UserId)
.InnerJoin<SysDept>((t, u, d) => u.DeptId == d.DeptId)
.LeftJoin<SupplierInvoice>((t, u, d, si) => t.Id == si.SupId)
.LeftJoin<SupplierChange>((t, u, d, si, ch) => t.Id == ch.SupId && ch.MostRecent)
.Where(exp.ToExpression())
.OrderByDescending(t => t.Id)
.Select((t, u, d, si, ch) => new SupplierVo
{
Id = t.Id.SelectAll(),
DeptName = d.DeptName,
NickName = u.NickName,
InvoiceStatus = si.Status,
ChangeStatus = ch.Status,
})
.ToPage(dto);

int count = DB.Queryable<T>().ClearFilter()
.InnerJoin<SysUser>((table, usr) => table.CreateBy == usr.UserId)
.InnerJoin<SysDept>((table, usr, dept) => usr.DeptId == dept.DeptId)
.Where(table => table.Id == Record.TableId)
.WhereIF(transition.Condition.IsNotEmpty(), transition.Condition, parameters)
.Count();

根据指定条件更新指定列:
Update(new SysUser(){ Status = 1 }, it => new { it.Status }, f => f.Userid == 1));
Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ Update_time = DateTime.Now, Title = "通知标题" });

另外还有不计其数的 CRUD 重载方法,覆盖了全部使用场景,开发效率很高
dengbojing
2023-11-23 19:30:22 +08:00
之前外包给移动做项目,是个二手项目接过来,接手给的 ibatis 加 pg ,我们就改改功能准备上了,结果移动是 oracle ,换个连接串跑起来,有些 sql 执行报错,直接被骂的狗血淋头,后面回来想了想换成了 hibernate ,然后公司跑 pg ,线上跑 oracle
BiChengfei
2023-11-23 19:40:57 +08:00
当然不是,mybatis 只是一个 Jdbc 工具类
totoro52
2023-11-23 21:17:35 +08:00
@shyangs idea 装个插件就能识别 而且可以属性跳转,属性不存在也会爆红, 并且支持生成简单的 crud 代码
mangojiji
2023-11-24 01:52:10 +08:00
@nothingistrue 我还是不能理解,Mybatis 也实现了比较基础的对象数据模型到关系数据模型的映射对吧。

为什么 Mybatis 不算是,在实现了哪些"缺失的功能"之后,它才能真正算是 ORM ?
mangojiji
2023-11-24 01:55:26 +08:00
若仅仅是要不要手写 SQL 的差别,Mybatis 也有一些能够自动动态生成 SQL 的组件我记得。。。以及 queryWrapper 之类的东西,也能够避免编写 sql 呀(甚至不需要一个用于 mapper 的 xml 文件),它为啥就不是 ORM ?
WDATM33
2023-11-24 09:20:28 +08:00
做报表查询还得手写 sql ,一次查询非日结表少则关联 3 ,4 张表,多的甚至能关联十几张表,里面又是临时表又是一堆子查询。经常是一个 sql 能写出几百行,这种感觉不手写 sql 更头疼
burymme11
2023-11-24 15:51:16 +08:00
@zhazi 我回复的 7 楼。漏了 @
burymme11
2023-11-24 15:57:56 +08:00
@shyangs 如果硬要在 xml 中写 SQL ,idea 有 mybatis 插件,有一些语法提示和自动填充,建议在外部写好,比如 datagrip 或者 navicate 等专业的 SQL IDE 中写好,再贴到 XML 中。
项目中,复杂 SQL 的占比不会很多,一般的业务查选,基于 BaseMapper 的接口就够用了,手写 SQL 的次数不多。

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

https://yangjunhui.monster/t/994353

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

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

© 2021 V2EX