mybatis对java自定义注解的使用——入门篇

转自;https://www.cnblogs.com/sonofelice/p/4980161.html

1.

最近在学习spring和ibatis框架。

以前在天猫实习时做过的一个小项目用到的mybatis,在其使用过程中,不加思索的用了比较原始的一种持久化方式:

在一个包中写一个DAO的接口,在另一个包里面写DAO的实现,使用sqlMapClient来从***-sql.xml中读取相应的sql。

 1 public interface IBaseDaoiBatis {
 2      Object get(String statementName);
 3 }
 4 public class BaseDaoiBatis implements IBaseDaoiBatis {
 5  public Object get(String statementName) {
 6         return getSqlMapClientTemplate().queryForObject(statementName);
 7     }
 8 }
 9 //对应的mybatis配置文件里面的sql:
10 <sqlMap>
11     <typeAlias alias="sonarBean" type="com.**--**.SonarScanDataDisplayBean" />
12     <select id="getSonarScanData" parameterClass="java.lang.Integer" resultClass="java.lang.String">
13         <![CDATA[
14             SELECT  name FROM mm_test  where id=#id#;  
15         ]]>
16     </select>
17 </sqlMap>

 

最近搭建了一个spring+ibatis的项目,发现了一种新的持久化方式:

只写一个dao的接口,在接口的方法中直接注解上用到的sql语句,觉得蛮巧妙的。借来用一下。注意,接口上方多了一个@Mapper注解。而每个方法上都是@Select() 注解,值为对应的sql。

1 @Mapper
2 public interface TestDao {
3     @Select("select id, name, name_pinyin from mm_test; ")
4     List<MmTest> selectAll();
5     
6     @Insert("insert into mm_test(id, name) values(#{id}, #{name})")  
7     public void insertUser(MmTest mmtTestS);    
8 }

那么这个@Mapper注解究竟是个什么东西,是怎么起到注解的作用的?ibatis是怎么来识别这种注解的呢?对我这个java小白来说,注解,是spring特有的东西嘛?自学java的时候好像很少接触注解啊。不过竟然有java.lang.annotation 这个包,这到底是怎么回事?

那我们先来看一下Mapper这个自定义注解的定义:

 1 import org.springframework.stereotype.Component;
 2 
 3 import java.lang.annotation.*;
 4 @Target({ ElementType.TYPE })
 5 @Retention(RetentionPolicy.RUNTIME)
 6 @Documented
 7 @Component
 8 public @interface Mapper {
 9     String value() default "";
10 }

 

 

关于自定义注解:(查的别人的博客:http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html)博客里面写的非常详细,并且注解的使用机制很容易理解。

拿上述的@Mapper来说,Retention选择的是RUNTIME策略,就是运行时注入。那么要在运行时获得注入的值,必然要用到java的反射机制。通过反射,拿到一个类运行时的方法变量等,来进行一系列的操作。

那我要考虑的下一个问题是,我定义的@Mapper,在我的工程里面是怎么识别的呢?

来看一下我spring的配置文件中关于mybatis的配置

 1 <!--mybatis-->
 2     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 3         <property name="dataSource" ref="dataSource" />
 4         <property name="configLocation">
 5             <value>classpath:myBatis/mapper.xml</value>
 6         </property>
 7     </bean>
 8     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
 9         <property name="basePackage" value="com.**.**.**.dao" />
10         <property name="annotationClass" value="com.nuomi.crm.annotation.Mapper"/>
11         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
12     </bean>

在org.mybatis.spring.mapper.MapperScannerConfigurer这个类里面,应该是会去扫描我自定义的com.nuomi.crm.annotation.Mapper这个类的。

 

 1 <configuration>
 2     <settings>
 3         <!-- 将下划线字段名称映射为驼峰变量  -->
 4         <setting name="mapUnderscoreToCamelCase" value="true" />
 5         <!-- 进制mybatis进行延迟加载 -->
 6         <setting name="lazyLoadingEnabled" value="false"/>
 7     </settings>
 8     <mappers>
 9     </mappers>
10 </configuration>

 

在我的mapper.xml里面只需要进行这一简单的配置就可以了(配置的含义后续补充)

接下来看一下mybatis自带的这个MapperScannerConfigurer究竟怎么实现的,来使用我这个自定义的注解@Mapper呢。

 1 public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
 2 private Class<? extends Annotation> annotationClass;
 3   public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
 4     this.annotationClass = annotationClass;
 5   }/**
 6    * {@inheritDoc}
 7    * 
 8    * @since 1.0.2
 9    */
10   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
11     if (this.processPropertyPlaceHolders) {
12       processPropertyPlaceHolders();
13     }
14 
15     ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
16     scanner.setAddToConfig(this.addToConfig);
17     scanner.setAnnotationClass(this.annotationClass);
18     scanner.setMarkerInterface(this.markerInterface);
19     scanner.setSqlSessionFactory(this.sqlSessionFactory);
20     scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
21     scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
22     scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
23     scanner.setResourceLoader(this.applicationContext);
24     scanner.setBeanNameGenerator(this.nameGenerator);
25     scanner.registerFilters();
26     scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
27   }
28 
29   /*
30    * BeanDefinitionRegistries are called early in application startup, before
31    * BeanFactoryPostProcessors. This means that PropertyResourceConfigurers will not have been
32    * loaded and any property substitution of this class' properties will fail. To avoid this, find
33    * any PropertyResourceConfigurers defined in the context and run them on this class' bean
34    * definition. Then update the values.
35    */
36   private void processPropertyPlaceHolders() {
37     Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
38 
39     if (!prcs.isEmpty() && applicationContext instanceof GenericApplicationContext) {
40       BeanDefinition mapperScannerBean = ((GenericApplicationContext) applicationContext)
41           .getBeanFactory().getBeanDefinition(beanName);
42 
43       // PropertyResourceConfigurer does not expose any methods to explicitly perform
44       // property placeholder substitution. Instead, create a BeanFactory that just
45       // contains this mapper scanner and post process the factory.
46       DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
47       factory.registerBeanDefinition(beanName, mapperScannerBean);
48 
49       for (PropertyResourceConfigurer prc : prcs.values()) {
50         prc.postProcessBeanFactory(factory);
51       }
52 
53       PropertyValues values = mapperScannerBean.getPropertyValues();
54 
55       this.basePackage = updatePropertyValue("basePackage", values);
56       this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);
57       this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);
58     }
59   }
60 
61 }

上面只是截取的关于annotation的代码片段.

scanner.setAnnotationClass(this.annotationClass);
这里会去扫描配置的那个注解类。

mybatis的内部实现会使用java反射机制来在运行时去解析相应的sql。

 

(上面写的还不是很完全,后续补充。)

 

转载于:https://www.cnblogs.com/sharpest/p/6097682.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/542187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java BigDecimal toBigIntegerExact()方法(带示例)

BigDecimal类的toBigIntegerExact()方法 (BigDecimal Class toBigIntegerExact() method) toBigIntegerExact() method is available in java.math package. toBigIntegerExact()方法在java.math包中可用。 toBigIntegerExact() method is used to convert this BigDecimal int…

Linux中的软件管理

1. 使用已有的网络安装资源安装软件 cd /etc/yum.repos.d/ (移动到yum源指向的文件配置目录下&#xff09; vim westos.repo &#xff08;新建文件&#xff0c;yum下后缀必须为.repo) 编辑这个文件里面写 [redhat] &#xff08;软件仓库名称&#xff09; namefirefox &#x…

楚留香ai人脸识别_戴口罩居然也能人脸识别?这些AI黑科技真的藏不住了.........

当人工智能遇见影像技术&#xff0c;将会释放出多少意想不到的巨大能量&#xff1f;「喔图知图实验室」瞄准当下的影像痛点&#xff0c;持续发力升级AI黑科技&#xff0c;带来两大必杀技——人脸识别再度升级、AI智能旋转校正。戴口罩也能识别——人脸识别升级戴口罩人脸识别如…

android--------Popupwindow的使用

2019独角兽企业重金招聘Python工程师标准>>> PopupWindow在Android.widget包下&#xff0c;项目中经常会使用到PopupWindow做菜单选项&#xff0c; PopupWindow这个类用来实现一个弹出框&#xff0c;可以使用任意布局的View作为其内容&#xff0c;这个弹出框是悬浮…

使用JavaScript中的示例的escape()函数

While transferring the data over the network or sometimes while saving data to the database, we need to encode the data. The function escape() is a predefined function in JavaScript, which encodes the given string. 在通过网络传输数据或有时将数据保存到数据库…

安装虚拟机的脚本

1. 先安装生成自动安装脚本的工具 yum install system-config-kickstart -y 2. 打开这个软件 system-config-kickstart 基本设置&#xff1a;更改时区为上海&#xff0c;设置root用户密码 2&#xff09;设置安装方法为网络安装&#xff0c;将共享的镜像文件地址正确填写 3&…

小小小游戏

写着玩 FlappyBird 视频:https://pan.baidu.com/s/1sljIR5z 游戏:https://pan.baidu.com/s/1ge8j7Ej 项目:https://pan.baidu.com/s/1eSysxpw Breakout 视频:https://pan.baidu.com/s/1gfhv4hd 项目:https://pan.baidu.com/s/1hs8xPly QBert 视频:https://pan.baidu.com/s/1s…

go在方法中修改结构体的值_[Go]结构体及其方法

结构体类型可以包含若干字段&#xff0c;每个字段通常都需要有确切的名字和类型。也可以不包含任何字段&#xff0c;这样并不是没有意义的&#xff0c;因为还可以为这些类型关联上一些方法&#xff0c;这里可以把方法看作事函数的特殊版本。函数事独立的程序实体&#xff0c;可…

to_number用法示例_Number()函数以及JavaScript中的示例

to_number用法示例Number()函数 (Number() function) Number() function is a predefined global function in JavaScript, it used to convert an object to the number. If the function is not able to convert the object in a number – it returns "NaN". (Rea…

系统延时任务及定时任务

1. 系统延时任务&#xff1a; at相关命令 at time 设定任务执行时间at> rm -fr /mnt/* 任务动作at> <EOT> <<ctrld 执行任务at的命令&#xff1a; -l ##查看任务列表-c …

cpn tools查看运行时间_Jmeter在Linux下的运行测试

一、JMeterApache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于Web应用测试&#xff0c;但后来扩展到其他测试领域。1.1、JMeter的作用能够对HTTP和FTP服务器进行压力和性能测试&#xff0c; 也可以对任何数据库进行同样…

css div滚动_如何使用CSS创建可垂直滚动的div?

css div滚动Introduction: 介绍&#xff1a; Dealing with divs has become a regularity and divs are used for many purposes like to structure our code and to segregate our various sections of codes. Besides, we are also aware of many properties that we can im…

Linux中磁盘分区的管理

1. 本地存储设备的识别 fdisk -l真实存在的设备cat /proc/partitions系统识别的设备blkid系统可使用的设备df系统正在挂载的设备 真实存在的设备不一定可识别&#xff0c;识别到的的设备不一定可使用 2. 设备的挂载和卸载 1&#xff09;设备名称 /dev/xdx …

python中时间的加减_python日期加减

python中关于时间和日期函数的常用计算总结 python中关于时间和日期函数有time和datatime 1.获取当前时间的两种方法: import datetime,time now = time.strftime("%Y-%m-%d %H:%M:%S") print now now = datetime.datetime.now()... 文章 技术小胖子 2017-11-08 848…

bst 删除节点_在BST中删除大于或等于k的节点

bst 删除节点Problem statement: 问题陈述&#xff1a; Given a BST and a value x, write a function to delete the nodes having values greater than or equal to x. The function will return the modified root. 给定一个BST和一个值x &#xff0c;编写一个函数删除值大…

游戏架构之二(转)

棋牌类游戏常用架构&#xff1a; 我从事过4年的棋牌类游戏开发&#xff0c;使用过的架构大致如上&#xff0c;各模块解释如下。 LoginServer&#xff1a; 登陆服务器&#xff0c;主要负责player 的登陆请求&#xff0c;验证player的合法性&#xff0c;为合法的player分配sessio…

对lvm介绍

1. 什么是LVM LVM是 Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制&#xff0c;用户在无需停机的情况下可以方便地调整各个分区大小。 lvm中的一些常见符号及意义 pv物理卷被lv命令处理过的物理分…

pythonweb自动化测试实例_[转载]python webdriver自动化测试实例

python webdriver自动化测试初步印象以下示例演示启动firefox&#xff0c;浏览google.com,搜索Cheese&#xff0c;等待搜索结果&#xff0c;然后打印出搜索结果页的标题from selenium import webdriverfrom selenium.common.exceptions import TimeoutExceptionfrom selenium.w…

repeated_Ruby中带有示例的Array.repeated_combination()方法

repeatedArray.repeated_combination()方法 (Array.repeated_combination() Method) In this article, we will study about Array.repeated_combination() method. You all must be thinking the method must be doing something which is related to creating combinations o…

ApacheHttpServer修改httpd.conf配置文件

转自&#xff1a;https://blog.csdn.net/dream1120757048/article/details/77427351 1. 安装完 Apache HTTP Server 之后&#xff0c;还需要修改一下配置文件。 Apache 的配置文件路径如下&#xff1a; C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf…