java中mapper层作用_Java的MyBatis框架中Mapper映射配置的使用及原理解析
Mapper的内置方法model层就是实体类,对应数据库的表。controller层是Servlet,主要是负责业务模块流程的控制,调用service接口的方法,在struts2就是Action。Service层主要做逻辑判断,Dao层是数据访问层,与数据库进行对接。至于Mapper是mybtis框架的映射用到,mapper映射文件在dao层用。
下面是介绍一下Mapper的内置方法:
1、countByExample ===>根据条件查询数量
1
2
3
4
5
6
7int countByExample(UserExample example);
//下面是一个完整的案列
UserExample example =new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("joe");
int count = userDAO.countByExample(example);
相当于:select count(*) from user where username='joe'
2、deleteByExample ===>根据条件删除多条
1
2
3
4
5
6
7
8int deleteByExample(AccountExample example);
//下面是一个完整的案例
UserExample example =new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("joe");
userDAO.deleteByExample(example);
相当于:delete from user where username='joe'
3、deleteByPrimaryKey===>根据条件删除单条
1
2int deleteByPrimaryKey(Integer id);
userDAO.deleteByPrimaryKey(101);
相当于:
1
2delete from user where id=101
4、insert===>插入数据
1
2
3
4
5
6
7
8
9int insert(Account record);
//下面是完整的案例
User user =new User();
//user.setId(101);
user.setUsername("test");
user.setPassword("123456")
user.setEmail("674531003@qq.com");
userDAO.insert(user);
相当于:
1insert into user(ID,username,password,email)values(101,'test','123456','674531003@qq.com');
5、insertSelective===>插入数据
1int insertSelective(Account record);
6、selectByExample===>根据条件查询数据
1
2
3
4
5
6
7
8
9
10
11
12List selectByExample(AccountExample example);
//下面是一个完整的案例
UserExample example =new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("joe");
criteria.andUsernameIsNull();
example.setOrderByClause("username asc,email desc");
List>list = userDAO.selectByExample(example);
相当于:select * from user where username ='joe' and username isnull order by username asc,email desc
//注:在iBator 生成的文件UserExample.java中包含一个static 的内部类 Criteria ,在Criteria中有很多方法,主要是定义SQL 语句where后的查询条件。
7、selectByPrimaryKey===>根据主键查询数据
1Account selectByPrimaryKey(Integer id);//相当于select * from user where id = 变量id
8、updateByExampleSelective===>按条件更新值不为null的字段
1
2
3
4
5
6
7
8
9
10int updateByExampleSelective(@Param("record") Account record,@Param("example") AccountExample example);
//下面是一个完整的案列
UserExample example =new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("joe");
User user =new User();
user.setPassword("123");
userDAO.updateByPrimaryKeySelective(user,example);
相当于:update user set password='123' where username='joe'
9、updateByExampleSelective===>按条件更新
1int updateByExample(@Param("record") Account record,@Param("example") AccountExample example);
10、updateByPrimaryKeySelective===>按条件更新
1
2
3
4
5
6
7
8int updateByPrimaryKeySelective(Account record);
//下面是一个完整的案例
User user =new User();
user.setId(101);
user.setPassword("joe");
userDAO.updateByPrimaryKeySelective(user);
相当于:
1update user set password='joe' where id=101
1
2
3
4
5
6
7
8int updateByPrimaryKeySelective(Account record);
//下面是一个完整的案例
User user =new User();
user.setId(101);
user.setPassword("joe");
userDAO.updateByPrimaryKeySelective(user);
相当于:update user set password='joe' where id=101
11、updateByPrimaryKey===>按主键更新
1
2
3
4
5
6
7
8
9int updateByPrimaryKey(Account record);
//下面是一个完整的案例
User user =new User();
user.setId(101);
user.setUsername("joe");
user.setPassword("joe");
user.setEmail("joe@163.com");
userDAO.updateByPrimaryKey(user);
相当于:
1update user set username='joe',password='joe',email='joe@163.com' where id=101
1
2
3
4
5
6
7
8
9int updateByPrimaryKey(Account record);
//下面是一个完整的案例
User user =new User();
user.setId(101);
user.setUsername("joe");
user.setPassword("joe");
user.setEmail("joe@163.com");
userDAO.updateByPrimaryKey(user);
相当于:
1update user set username='joe',password='joe',email='joe@163.com' where id=101
解析mapper的xml配置文件我们来看看mybatis是怎么读取mapper的xml配置文件并解析其中的sql语句。
我们还记得是这样配置sqlSessionFactory的:
1
2
3
4
5
6
这里配置了一个mapperLocations属性,它是一个表达式,sqlSessionFactory会根据这个表达式读取包com.xxx.mybaits.mapper下面的所有xml格式文件,那么具体是怎么根据这个属性来读取配置文件的呢?
答案就在SqlSessionFactoryBean类中的buildSqlSessionFactory方法中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21if (!isEmpty(this.mapperLocations)) {
for (Resource mapperLocation :this.mapperLocations) {
if (mapperLocation ==null) {
continue;
}
try {
XMLMapperBuilder xmlMapperBuilder =new XMLMapperBuilder(mapperLocation.getInputStream(),
configuration, mapperLocation.toString(), configuration.getSqlFragments());
xmlMapperBuilder.parse();
}catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation +"'", e);
}finally {
ErrorContext.instance().reset();
}
if (logger.isDebugEnabled()) {
logger.debug("Parsed mapper file: '" + mapperLocation +"'");
}
}
}
mybatis使用XMLMapperBuilder类的实例来解析mapper配置文件。
1
2
3
4
5
6
7
8
9
10
11
12public XMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map sqlFragments) {
this(new XPathParser(reader,true, configuration.getVariables(),new XMLMapperEntityResolver()),
configuration, resource, sqlFragments);
}
private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map sqlFragments) {
super(configuration);
this.builderAssistant =new MapperBuilderAssistant(configuration, resource);
this.parser = parser;
this.sqlFragments = sqlFragments;
this.resource = resource;
}
接着系统调用xmlMapperBuilder的parse方法解析mapper。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public void parse() {
//如果configuration对象还没加载xml配置文件(避免重复加载,实际上是确认是否解析了mapper节点的属性及内容,
//为解析它的子节点如cache、sql、select、resultMap、parameterMap等做准备),
//则从输入流中解析mapper节点,然后再将resource的状态置为已加载
if (!configuration.isResourceLoaded(resource)) {
configurationElement(parser.evalNode("/mapper"));
configuration.addLoadedResource(resource);
bindMapperForNamespace();
}
//解析在configurationElement函数中处理resultMap时其extends属性指向的父对象还没被处理的节点
parsePendingResultMaps();
//解析在configurationElement函数中处理cache-ref时其指向的对象不存在的节点(如果cache-ref先于其指向的cache节点加载就会出现这种情况)
parsePendingChacheRefs();
//同上,如果cache没加载的话处理statement时也会抛出异常
parsePendingStatements();
}
mybatis解析mapper的xml文件的过程已经很明显了,接下来我们看看它是怎么解析mapper的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27private void configurationElement(XNode context) {
try {
//获取mapper节点的namespace属性
String namespace = context.getStringAttribute("namespace");
if (namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
//设置当前namespace
builderAssistant.setCurrentNamespace(namespace);
//解析mapper的节点
cacheRefElement(context.evalNode("cache-ref"));
//解析mapper的节点
cacheElement(context.evalNode("cache"));
//解析mapper的节点
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
//解析mapper的节点
resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析mapper的节点
sqlElement(context.evalNodes("/mapper/sql"));
//使用XMLStatementBuilder的对象解析mapper的、、、节点,
//mybaits会使用MappedStatement.Builder类build一个MappedStatement对象,
//所以mybaits中一个sql对应一个MappedStatement
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
}catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
}
}
configurationElement函数几乎解析了mapper节点下所有子节点,至此mybaits解析了mapper中的所有节点,并将其加入到了Configuration对象中提供给sqlSessionFactory对象随时使用。这里我们需要补充讲一下mybaits是怎么使用XMLStatementBuilder类的对象的parseStatementNode函数借用MapperBuilderAssistant类对象builderAssistant的addMappedStatement解析MappedStatement并将其关联到Configuration类对象的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75public void parseStatementNode() {
//ID属性
String id = context.getStringAttribute("id");
//databaseId属性
String databaseId = context.getStringAttribute("databaseId");
if (!databaseIdMatchesCurrent(id, databaseId,this.requiredDatabaseId)) {
return;
}
//fetchSize属性
Integer fetchSize = context.getIntAttribute("fetchSize");
//timeout属性
Integer timeout = context.getIntAttribute("timeout");
//parameterMap属性
String parameterMap = context.getStringAttribute("parameterMap");
//parameterType属性
String parameterType = context.getStringAttribute("parameterType");
Class> parameterTypeClass = resolveClass(parameterType);
//resultMap属性
String resultMap = context.getStringAttribute("resultMap");
//resultType属性
String resultType = context.getStringAttribute("resultType");
//lang属性
String lang = context.getStringAttribute("lang");
LanguageDriver langDriver = getLanguageDriver(lang);
Class> resultTypeClass = resolveClass(resultType);
//resultSetType属性
String resultSetType = context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
String nodeName = context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
//是否是节点
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
//flushCache属性
boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
//useCache属性
boolean useCache = context.getBooleanAttribute("useCache", isSelect);
//resultOrdered属性
boolean resultOrdered = context.getBooleanAttribute("resultOrdered",false);
// Include Fragments before parsing
XMLIncludeTransformer includeParser =new XMLIncludeTransformer(configuration, builderAssistant);
includeParser.applyIncludes(context.getNode());
// Parse selectKey after includes and remove them.
processSelectKeyNodes(id, parameterTypeClass, langDriver);
// Parse the SQL (pre: and were parsed and removed)
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
//resultSets属性
String resultSets = context.getStringAttribute("resultSets");
//keyProperty属性
String keyProperty = context.getStringAttribute("keyProperty");
//keyColumn属性
String keyColumn = context.getStringAttribute("keyColumn");
KeyGenerator keyGenerator;
String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId,true);
if (configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = configuration.getKeyGenerator(keyStatementId);
}else {
//useGeneratedKeys属性
keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
?new Jdbc3KeyGenerator() :new NoKeyGenerator();
}
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
由以上代码可以看出mybaits使用XPath解析mapper的配置文件后将其中的resultMap、parameterMap、cache、statement等节点使用关联的builder创建并将得到的对象关联到configuration对象中,而这个configuration对象可以从sqlSession中获取的,这就解释了我们在使用sqlSession对数据库进行操作时mybaits怎么获取到mapper并执行其中的sql语句的问题。
java中mapper层作用_Java的MyBatis框架中Mapper映射配置的使用及原理解析相关推荐
- 【MyBatis框架】高级映射-一对一查询
一对一查询 根据上面我们分析的订单商品数据模型(链接:12.订单商品数据模型-分析思路.txt),我们来写一下有关一对一的查询,分别使用了resultType和resultMap指定输出参数类型 1. ...
- spring service 怎么拿到数据源信息_SSM(SpringMVC + Spring + MyBatis)中各层作用及关系Ⅰ...
1.持久层:DAO层(mapper层)(属于mybatis模块) DAO层:主要负责与数据库进行交互设计,用来处理数据的持久化工作. DAO层的设计首先是设计DAO的接口,也就是项目中你看到的Dao包 ...
- java中flush函数作用_Java语言中flush()函数作用及使用方法详解
最近在学习io流,发现每次都会出现flush()函数,查了一下其作用,起作用主要如下 //------–flush()的作用--------– 笼统且错误的回答: 缓冲区中的数据保存直到缓冲区满后才写 ...
- java类与对象作用_Java类与对象
●类和对象的关系: 一:类是对同一类事物(对象)的抽象,对象实际存在的该类的各种实体. 二:面向对编程的核心:找合适的对象来做合适的事. 三:Java中找到对象: 1):sun自己定义好的类,必须知道 ...
- AD使用总结--2__PCB中各层作用详解
一直以来,对PCB中各层,比如:solder层.paste层.Top overlay层等等这些一知半解.今天仔细看了下,向大家介绍一下,有不对的地方还请指正. 1.mechanical机械层是定义整个 ...
- java的复合语句的作用_Java复合语句的使用方法详解
与 C 语言及其他语言相同, Java 语言的复合语句是以整个块区为单位的语句,所以又称为块语句.下面我们来看看有关复合语句的使用方法和实例. 复合语句由开括号"{"开始,闭括号& ...
- mybatis框架中的mapper.xml文件中的头部代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-/ ...
- java daemon线程的作用_JAVA DAEMON线程的理解
java线程分两种:用户线程和daemon线程.daemon线程或进程就是守护线程或者进程,但是java中所说的daemon线程和linux中的daemon是有一点区别的. linux中的daemon ...
- java实现导出excel表_java实现导出网页中的表格为Excel
将网页中的table数据,导出到excel表格,可以使用java POI实现. java poi是java中操作excel的工具,支持excel的导入与导出,一般有三种形式: 1.HSSFWorkbo ...
最新文章
- 从多媒体技术演进看AI技术
- torch max 判断与筛选
- SAP 采购订单打印完后不可以取消审批
- 使用JestClient操作ElasticSearch
- asp.net mysql 增删该查_asp.net 数据库的增删改查
- Linux工作笔记022---查看Centos 内核版本号
- matlab中round函数_Excel中round函数的使用方法
- mysql 子表 关联查询语句_MySQL-基本查询语句及方法,连表和子查询
- python输入人名对话_对话框中的用户输入
- Axure导入元件库和使用
- 无线路由器的AP、Client、WDS、WISP使用功能图解(清晰明了)
- 安装spacy遇到的问题
- 上传截断_文件上传路径截断实例
- 【自动驾驶】碰撞检测算法
- android虹软人脸识别简书,C# 离线人脸识别 虹软ArcFace 2.0 demo
- 制作CentOS 6.4 U盘启动安装盘
- 炫龙毁灭者KP2笔记本U盘重装系统方法图文详细教学
- Effective Java读书笔记(二)
- aiohttp实战(路飞学城IT)和Event loop is closed问题解决
- USB设备及硬盘自动运行病毒免疫工具
热门文章
- DataPipeline丨LinkedIn元数据之旅的最新进展—Data Hub
- 《信息与编码》考试复习笔记6----第六章连续信源熵和信道容量(考点在连续信道容量)
- miui相机位置服务器,MIUI12相机变在哪呢?小米官方给你说说全新的设计
- SAP-ABAP性能优化之构建嵌套结构的哈希表
- 拉勾网数据分析师职位分析
- 使用Weevely工具上传一句话木马
- 数据库系统概论 第七章设计数据库
- macosx10.13运行go报dyld: Symbol not found: _SecTrustEvaluateWithError错误的解决办法
- mysql host 为%_mysql中host为%是什么意思
- 英雄帖:乌镇巴比特加速器潜力项目DemoDay,虚位以待