1
ChoateYao 350 天前
不是,人家就是 Object Mapper ,缺少关系连接和业务逻辑实现。
|
2
Goooooos 350 天前
你理解的 ORM 是啥?
|
3
Masoud2023 350 天前
按我的理解能手写 sql 的都不叫 ORM ,ORM 应该是 SQLAlchemy 那种直接能拿模型生成 SQL 的
|
4
wanguorui123 350 天前
1 、思想:
mybatis 面向过程开发 JPA ( Hibernate )面向对象开发 2 、侧重点: mybatis 采用 XML 管理 SQL 比较直观,查询多的场景比较自由灵活、缺点存一些符号冲突(<>),管理思想还是面向过程,需要通过 Plus 加强对象管理 JPA 将数据库完全映射为对象需要有业务的整体设计能力,JPA 优势是简单的 CURD 根本不写 SQL ,JPA 缺点就是需要了解数据状态同步管理,复杂的业务尤其需要了解实体各个阶段状态,以及复杂的连表查询需要调用 JPA 的原生查询接口或者 DSL 3 、抽象能力 mybatis 使用原生的 SQL 方言,迁移能力比较差 JPA 使用 HQL 屏蔽了底层方言差异抽象的比较彻底,迁移能力比较强 |
5
weijancc 350 天前
这个问题被讨论烂了都, 明明百度就有一堆答案
|
6
kevinlia0 350 天前
By chatgpt
MyBatis 是一种持久层框架,通常被称为数据映射框架( Data Mapping Framework ),而不是严格意义上的对象关系映射( ORM )框架。尽管它与 Hibernate 等 ORM 框架有一些相似之处,但它们之间存在一些关键的区别。 1. **SQL 控制:** MyBatis 更注重对 SQL 的控制,它允许开发者编写和优化原生 SQL 查询,而不是完全依赖于框架生成的 SQL 。这使得开发者可以更细粒度地控制数据库访问,针对复杂的查询进行优化。 2. **映射方式:** 在 MyBatis 中,对象和数据库表之间的映射是通过 XML 或注解进行配置的,而不是像 Hibernate 那样完全基于对象的映射。这意味着在 MyBatis 中,你需要显式地指定如何将对象属性映射到数据库列,而在 ORM 框架中,这一切通常是自动完成的。 3. **对象状态:** 在 ORM 框架中,对象通常处于持久化状态,而在 MyBatis 中,对象通常是短暂的,它们只在执行 SQL 语句时与数据库进行交互。这使得 MyBatis 更加适用于需要精细控制数据库访问的场景。 总的来说,尽管 MyBatis 可以执行对象到数据库表的映射和数据库查询结果到对象的映射,但它更强调 SQL 的控制和灵活性,相较于 Hibernate 等严格的 ORM 框架而言更接近数据映射框架。因此,如果你更喜欢自己编写和优化 SQL 语句,或者需要处理复杂的数据库操作,MyBatis 可能是一个更好的选择。如果你更倾向于对象的自动映射和更高级的持久化管理,那么 Hibernate 等 ORM 框架可能更适合你。 |
7
iceloop 350 天前
ORM 框架的核心是自动化地将对象模型映射到关系型数据库,Mybatis 一个垃圾的 SQL 映射框架,无论怎么说都够不上 ORM ,中国特色开发主义才让 Mybatis 在中国有地位,早应该被时代洪流淘汰的垃圾产物
|
8
burymme11 350 天前 5
我一点都不觉的 mybatis 垃圾,复杂的 sql 处理直接写在 xml 里,直观明了,排错调试很方便。
使用 ORM 框架还能用出优越感?这玩意还能搞出鄙视链? WFT ?? |
9
Mandelo 350 天前
半 ORM
|
12
XCFOX 350 天前 2
跟 C# 的 EF Core 比,MyBatis 最多算一个 SQL Builder 。
好的 ORM 应该尽可能减少 SQL 的书写,尽量自动化,尽量贴近语言原生语法。 看过 C# 的 Entity Framework 、Ruby 的 Active Record 、php 的 Eloquent 、Typescript 的 MikroORM 、kotlin 的 Ktorm 才知道什么是好用的 ORM 。相比之下 Java 、go 生态下缺少好用的 ORM 框架。 优雅的 ORM (EF Core)是这么更新的: using (var context = new BloggingContext()) { var blog = context.Blogs.Single(b => b.Url == "http://example.com"); blog.Url = "http://example.com/blog"; context.SaveChanges(); } 使用 C# LINQ 表达式写查询,直接修改 blog.URL 的值再保存修改,真正的面向对象、真正的自动化,开发人员甚至不需要深入了解 SQL ,极大减轻了开发时的负担; GORM 是这么更新的: db.Model(Blog{}).Where("Url = ?", "http://example.com").Updates(Blog{Url: "http://example.com/blog"}) 在 gorm 自身的语法 "db.Model().Where().Updates()"之中混入半句 sql "url = ? ",这就要求开发人员既要会 sql 也要熟悉 gorm 额外的语句,开发时的性质负担并没有减少; |
14
XCFOX 350 天前
@kidlj #13
ent 是这么更新的: n, err := client.Blog. Update(). Where( blog.Url("http://example.com"), ). SetUrl("http://example.com/blog"). SetTitle("The Last Theorem"). SetAuthor("Clarke"). Save(ctx) ent 比 gorm 要严谨得多,而代价则是啰嗦的指令式调用,极大损失了灵活性。 与 ent 相比,同样使用代码生成的 node.js 的 prisma 是这么更新的: const bolg = await prisma.blog.update({ where: { url: "[email protected]", }, data: { url: "Viola the Magnificent", title: "The Last Theorem", author: "Clarke", }, }); prisma 将查询参数和更新数据全都赛进 update() 中,更容易实现动态参数。 |
15
gitrebase 350 天前
#6 GPT 说的没错,MyBatis 纯纯的 Data Mapping ,跟 Object Relation Mapping 扯不上一点关系
MyBatis 跟 Go 生态里的 sqlx 、squirrel 这种 SQL builder 是差不多的 BTW ,Java 和 Go 里感觉没有一个 ORM 用起来是真的舒服的,他们对“网上说的‘复杂的场景’”都比较乏力,因此个人认为在 SQL 没有特别复杂的情况下(感觉没有太多表的 Join 就不算太复杂)直接用 JPA 、GORM 之类的完全没问题(绝大多数项目都到不了这程度) |
16
tunzao 350 天前
是不是,又有什么关系呢?
|
17
nothingistrue 350 天前 1
@XCFOX #10 你所举例的代码中,EF Core 才是 ORM ,因为它的操作方法上完全看不出 SQL 的影子。GORM 还有后面的 ent 并不是 ORM ,因为它们的 Where()、Update()、SetXXX() 等方法,只不过是 SQL 的翻版,他们的数据模型基础还是关系模型。
ORM 的全称是 Object Relational Mapping ,是对象数据模型跟关系数据模型之间的映射,它的重点是让你不必跳出面向对象开发的思路,就能使用关系数据库作为数据持久层。并不是简简单单的隐藏 SQL 。 |
18
cheng6563 350 天前 1
严格的 ORM 不会让你碰到 SQL 。
并且静态语言上的 ORM 框架还应当具备语法检查,这点就 C#做的比较好,Java 的 Jinq 只能凑合用。其他的 ORM 框架或多或少都还是要涉及手动拼接 SQL MyBatis 对数据库所有操作都要自己写 SQL ,他只是提供了个对 JDBC 优化的模板引擎,算不上 ORM 另外,直接在程序里嵌 SQL 的都是大便框架,尤其是那些自创 DSL 来隐藏 SQL 细节的框架 |
19
gitrebase 350 天前
@cheng6563 #18 哈哈哈哈最近刚看到有个 typescript 到 orm 框架说自己是 modern ORM ,但一看 README 它自己定义了一个 DSL 后我就直接懒得看了
|
20
lolizeppelin 350 天前
|
22
shyangs 350 天前
|
23
thinkershare 350 天前
你如果.NET 的 ORM 框架,立马就能理解 ORM 和各种 SQL Helper 的差别。同意楼上的,自定义 DSL 的都是狗屎。
|
24
songteng0604 349 天前
//来自 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 的方法。 |
25
ZZ74 349 天前
作为一个 CURDer ,你永远不知道查询条件会有多奇葩,所以我选择 ibatis 这类,碰到复杂能手写 sql ,简单还高效。简单场景 写过的几乎都能复用。
|
26
tzengshinfu 349 天前
那 Mybatis dynamic-sql( https://mybatis.org/mybatis-dynamic-sql/docs/select.html)能算吗?
|
27
gowk 349 天前
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 重载方法,覆盖了全部使用场景,开发效率很高 |
28
dengbojing 349 天前 via Android
之前外包给移动做项目,是个二手项目接过来,接手给的 ibatis 加 pg ,我们就改改功能准备上了,结果移动是 oracle ,换个连接串跑起来,有些 sql 执行报错,直接被骂的狗血淋头,后面回来想了想换成了 hibernate ,然后公司跑 pg ,线上跑 oracle
|
29
BiChengfei 349 天前
当然不是,mybatis 只是一个 Jdbc 工具类
|
31
mangojiji OP @nothingistrue 我还是不能理解,Mybatis 也实现了比较基础的对象数据模型到关系数据模型的映射对吧。
为什么 Mybatis 不算是,在实现了哪些"缺失的功能"之后,它才能真正算是 ORM ? |
32
mangojiji OP 若仅仅是要不要手写 SQL 的差别,Mybatis 也有一些能够自动动态生成 SQL 的组件我记得。。。以及 queryWrapper 之类的东西,也能够避免编写 sql 呀(甚至不需要一个用于 mapper 的 xml 文件),它为啥就不是 ORM ?
|
33
WDATM33 349 天前
做报表查询还得手写 sql ,一次查询非日结表少则关联 3 ,4 张表,多的甚至能关联十几张表,里面又是临时表又是一堆子查询。经常是一个 sql 能写出几百行,这种感觉不手写 sql 更头疼
|