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.pswp.cn/news/542187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542187.shtml
英文地址,請注明出處:http://en.pswp.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…