在Mybatis框架中,有两种特殊的占位符用于处理SQL语句中的参数:{...}和${...}。它们之间的核心区别是什么?简单来说,{}用于预编译处理,可以有效防止SQL注入,提高系统安全性;而${}则是直接对传递进来的参数进行字符串替换。
当遇到实体类中的属性名和数据库表中的字段名不一致时,我们有两种常见的处理方式。第一种是通过在查询的SQL语句中定义字段名的别名,让别名与实体类的属性名一致。例如:
```sql
select order_id as id, order_no as orderno, order_price as price from orders where order_id={id};
```
第二种方式则是通过建立映射关系,一一对应字段名和实体类属性名。这种方式更为灵活,尤其是当字段名和实体类属性名之间存在复杂差异时。我认为第二种方式在实际应用中可能会更为实用。
在Mybatis中,执行查询的方式多样且灵活。当需要从`user_user_t`表中根据用户名和地区筛选用户时,我们可以使用占位符`{0}`和`{1}`来进行查询。这种参数注入的方式使得数据库操作更为便捷。
而在接口`usermapper`中,使用`@param`注解来明确方法参数的意义,如用户名和密码。这种方式使得代码更加清晰易懂。当需要从`some_table`表中根据给定的用户名和哈希密码查询用户时,可以这样写:
```java
public interface UserMapper {
User selectUser(@Param("username") String username, @Param("hashedpassword") String hashedpassword);
}
```
当参数过多时,我们可以采用Map集合来装载参数,这种方式在处理复杂查询时尤为方便。例如,进行分页查询时,我们可以将起始位置和结束位置作为Map的键值对来传递给SQL。
Mybatis动态SQL是一项强大而实用的功能。在Xml映射文件中,我们可以使用各种动态SQL标签来根据条件动态生成SQL语句。这些标签包括`trim`、`where`、`set`、`foreach`、`if`、`choose`、`when`、`otherwise`和`bind`等。
其执行原理是通过Mybatis结合OGNL(对象图导航语言)来解析sql参数对象中的表达式值,根据这些值的变动来动态拼接SQL语句。这使得我们可以灵活地根据条件来生成和执行不同的SQL语句。
关于Mybatis的Xml映射文件,不同的Xml映射文件中,如果配置了namespace,那么id是可以重复的。因为Statement实际上是namespace+id的组合。如果没有配置namespace,则相同的id会导致覆盖。
Mybatis被称为半自动ORM映射工具,因为在查询关联对象或关联集合对象时,需要手动编写sql来完成,而全自动工具如Hibernate则可以根据对象关系模型直接获取。
至于Dao接口的工作原理,它其实就是Mapper接口。接口的全限名对应映射文件中的namespace,接口的方法名对应映射文件中的MappedStatement的id。接口方法内的参数就是传递给sql的参数。当参数不方法是可以重载的。
Mybatis接口深度解析:Mapper、插件与延迟加载
Mapper接口是Mybatis的核心组成部分,它没有实现类。当我们调用接口方法时,会使用接口的全限名和方法名拼接的字符串作为key值,以唯一确定一个MappedStatement。例如,“com.mybatis3.mappers.StudentDao.findStudentById”就能够唯一找到对应的MappedStatement。在Mybatis中,每一个xml标签都会被解析为一个MappedStatement对象。
值得注意的是,Dao接口里的方法是不能重载的,因为Mybatis采用全限名+方法名的保存和寻找策略。Dao接口的工作原理基于JDK动态代理。当Mybatis运行时,它会使用JDK动态代理为Dao接口生成代理对象proxy。这个代理对象会拦截接口方法,转而执行MappedStatement所代表的SQL语句,然后将执行结果返回。
相对于IBatis,Mybatis有几个重要的改进。其中,接口绑定是其中之一,包括注解绑定sql和xml绑定Sql。动态SQL也由原来的节点配置变成了OGNL表达式,更加灵活方便。Mybatis在一对一和一对多的查询中,引入了association和collection节点的概念,这些都配置在resultMap里面。
接口绑定有两种实现方式:一种是通过注解绑定,即在接口的方法上加上@Select、@Update等注解,这些注解中包含SQL语句来实现绑定;另一种是通过xml文件来绑定SQL语句,这种情况下需要指定xml映射文件里的namespace为接口的全路径名。
Mybatis的插件运行原理基于JDK的动态代理。Mybatis可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件。使用JDK的动态代理,为需要拦截的接口生成代理对象,以实现接口方法拦截功能。每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法。
至于延迟加载,Mybatis支持association关联对象和collection关联集合对象的延迟加载。在Mybatis配置文件中,可以配置是否启用延迟加载(lazyLoadingEnabled=true|false)。它的实现原理是在查询数据时,如果关联的数据没有被立即加载,那么在访问这些数据时才会发起新的查询,从而提高数据库性能。
探究Mybatis技术之延迟加载与Executor执行器
当我们探讨Mybatis的运作机制时,延迟加载是一个不可忽视的核心原理。这一技术主要依赖于CGLIB创建目标对象的代理对象。当调用目标方法时,会进入一个方法。例如,当我们尝试调用a.getB().getName()时,如果a.getB()返回的是null值,会立即启动。它会发送一个预先准备好的查询关联B对象的SQL语句,将B对象检索出来,然后通过a.setB(b)将其与a对象关联。这样,a.getB().getName()方法就能顺利执行了。这就是延迟加载的基本流程。
其实,不只是Mybatis,包括Hibernate等大多数框架,都采用了类似的延迟加载原理。
接下来,我们来了解一下Mybatis中的Executor执行器。Mybatis有三种基本的Executor:SimpleExecutor、ReuseExecutor和BatchExecutor。
SimpleExecutor是最基础的执行器,每次执行update或select操作时,都会开启一个新的Statement对象,操作完成后立刻关闭。
ReuseExecutor则更注重Statement对象的管理和复用。执行update或select时,它以sql语句作为key去查找已有的Statement对象,如果找到就重用,否则就创建一个新的。重要的是,使用完毕后,它并不会关闭Statement对象,而是将其存放在一个Map中,供下次使用。
BatchExecutor主要用于执行update操作。它会将所有sql语句添加到批处理中,然后一次性执行。它缓存了多个Statement对象,每个Statement对象在addBatch()后被使用,等待executeBatch()批处理逐一执行。这种执行器特别适合需要批量操作数据库的场景。
这些Executor的特点都严格限制在SqlSession的生命周期范围内。
当我们对比Mybatis和Hibernate时,可以发现两者有着不同的特点。Mybatis虽然不是一个完全的ORM框架,但它通过灵活的SQL配置和Java对象的映射,实现了java对象和sql语句之间的无缝对接。Mybatis的学习门槛相对较低,特别适合互联网软件、企业运营类软件等需求变化频繁的开发场景。它的灵活度也意味着它无法实现数据库的完全无关性。
而Hibernate则具有强大的对象/关系映射能力,对于关系模型要求高的软件,使用Hibernate可以大大提高开发效率。但它的学习门槛较高,如何设计O/R映射、在性能和对象模型之间如何权衡等都需要丰富的经验和能力。
无论是Mybatis还是Hibernate,只要能在有限的资源环境下满足用户的需求、做出维护性和扩展性良好的软件架构,都是好的选择。选择框架最重要的是看它是否适合你的项目需求。
参考资料:可以从一些博客和论坛中找到更多关于Mybatis和Hibernate的详细信息和经验分享。例如CSDN博客等网站上有很多专家分享他们的经验和见解。同时请注意以上内容来源于Java3y的原创文章。
文章来自《钓虾网小编|www.jnqjk.cn》整理于网络,文章内容不代表本站立场,转载请注明出处。