聊聊 MyBatis 的历史,mysql 原理详解
<mappers>
<mapper resource="mapper/user.xml"/>
</mappers>
</configuration>
下面是某个 mapper 的配置
<?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="xml">
<select id="listUser" resultType="user">
select * from? user;
</select>
</mapper>
这个 mapper 里面有个 namespace,我一直不知道它是什么意思。没关系这个 namespace 先随便写,一会就知道它是什么意思了。
增加 entity
package entity;
/**
@program: parent_pro
@description:
@author: 渭水
@create: 2021/07/21
*/
public class User {
private int id;
private String username;
private String? password;
private String nickname;
// 省略 getset
}
最后的启动类
package xml;
import entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
@program: parent_pro
@description:
@author: 渭水
@create: 2021/07/21
*/
public class MyBatisWithXML {
public static void main(String[] args) {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
// 最后通过 session 的 selectList() 方法调用 sql 语句 listStudent
List<User> userList = session.selectList("listUser");
for (User student : userList) {
System.out.println("ID:" + student.getId() + ",NAME:" + student.getUsername());
}
}
}
我们看看整个项目个结构图:
数据库那边,我已经建立好了,大家看看:
运行项目就能看到:
OK,至此项目已经可以运行了。
然后我们分析一下代码:
关于别名
一段一段看
<select id="listUser" resultType="user">
select * from? user limit 5;
</select>
这个里面的 resultType,我们不用看框架,大概就懂它指的是把下面的 sql 语句执行的结果,包装成什么类型。
那么光写个 user,mybatis 知道这个 user 是个什么东西么?
<typeAliases>
<package name="entity"/>
</typeAliases>
上面一段代码的语义就是,把 entity 下面的实体都加一个别名,而别名就是类名。所以 mybatis 就知道上面的 user 其实对应的就是 entity.User 这个类。
关于 namespace
上面已经有了一个 mapper,我现在再加一个 mapper 如下:
和之前那个的区别就是一个 limit 5,一个 limit 10
然后让 mybatis 的主配置文件感知到这个 user2.xml
<mappers>
<mapper? resource="mapper/user.xml"/>
<mapper? resource="mapper/user2.xml"/>
</mappers>
然后运行代码会发现:
说的很清楚 listUser 这个 id 重复了。
在线上工程里,要保证所有的 sql 的 id 都不重复有点困难,所以引入了 namespace 的概念。如果一旦有重复的 id,那么 session 调用的时候得指定 namespace。
List<User> userList = session.selectList("xml.listUser");
原生的 mybatis(使用注解)
================
@Mapper
public interface PersonMapper {
@Select("select id,name ,age from person where id = #{id}")
Person getPersonById(int id);
@Select("<script>"
+"select * from person where 1=1"
+"<if test='name2 != null'> and name = #{name2}" +"</if>"
+"<if test='age != null'> and age = #{age}" +"</if>"
+"</script>")
List<Person> getList(@Param("name2") String name,@Param("age") String age);
@SelectProvider(type = UserDaoProvider.class, method = "getPersonByPara")
Person getPersonByPara(@Param("name") String name, @Param("age") String age);
}
如上面所示
调用的时候就直接写
PersonMapper personMapper = session.getMapper(PersonMapper.class);
Person result = personMapper.getPersonByPara("渭水","");
List<Person> list = personMapper.getList(null,"25");
其实,这就回到我在序言里说的了,在 java 代码里写脚本语言很丑,代码很难读。
我们可以用一个单独的 java 方法来产生 sql 语句,如下;
@Mapper
public interface PersonMapper {
@SelectProvider(type = UserDaoProvider.class, method = "getPersonByPara")
Person getPersonByPara(@Param("name") String name, @Param("age") String age);
}
public class UserDaoProvider {
public String getPersonByPara(Map<String, Object> para) {
String sql = new SQL() {
{
SELECT("id, name, age");
FROM("person");
if (StringUtils.isNotBlank("" + para.get("name"))) {
WHERE("name='" + para.get("name")+"'");
}
if (StringUtils.isNotBlank("" + para.get("age"))) {
WHERE("age=" + para.get("age"));
}
}
}.toString();
System.out.println("----" + sql);
return sql;
}
}
Mybatis 与 spring
==============
通过上面我们可以看到,不管是用 xml 配置,还是直接在 java 文件里写注解,最终都是通过 SqlSession 来指向下一步的操作的。
所以,就算我们把 mybatis 与 spring 整合,其实核心原理还是依赖 SqlSession 的。
第一步,我们先去掉之前的 mybatis 依赖,改成
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
然后在 spring 的 xml 里面加上
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
dataSource 的相关代码我这边就赘述。
然后,具体来说,整合的思路有两种:
MapperFactoryBean
把我们的 mapper 放到 MapperFactoryBean 里面
public interface UserMapper {
@Select("SELECT * FROM users WHERE
id = #{userId}")
User getUser(@Param("userId") String userId);
}
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
使用的时候
public class FooServiceImpl implements FooService {
private final UserMapper userMapper;
public FooServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User doSomeBusinessStuff(String userId) {
return this.userMapper.getUser(userId);
}
}
我们怎么说也是写了年代码的人了,稍微往下追一下吧
先说 userMapper 它最后是 MapperFactoryBean,哦,FactoryBean,来大家看一下:
[https://blog.csdn.net/dlf123321/article/details/47856937](
),也就是说最终 userMapper 是 MapperFactoryBean 调用 getObject 的结果,我们看看代码
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSessionTemplate sqlSessionTemplate;
评论