中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

@InsertProvider執行的原理是什么

發布時間:2022-07-06 11:54:27 來源:億速云 閱讀:170 作者:iii 欄目:開發技術

本篇內容介紹了“@InsertProvider執行的原理是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

@InsertProvider執行原理

1.首先要拼接處insert語句

其中包含入參,與數據庫表字段的映射字段。

在執行Provider類里面的動態插入sql的時候,程序會調用 AbstractSQL這個抽象類,執行里面的兩個拼接字符串的方法

    public T INSERT_INTO(String tableName) {
        this.sql().statementType = AbstractSQL.SQLStatement.StatementType.INSERT;
        this.sql().tables.add(tableName);
        return this.getSelf();
    }
 
    public T VALUES(String columns, String values) {
        this.sql().columns.add(columns);
        this.sql().values.add(values);
        return this.getSelf();
    }

這個抽象class里面有一個私有的靜態類SQLStatement和私有靜態SalfAppendable類。

SQLStatement類里面有一個共有靜態枚舉類,里面有它的一個私有構造函數,枚舉被設計成是單例模式,即枚舉類型會由JVM在加載的時候,實例化枚舉對象,你在枚舉類中定義了多少個就會實例化多少個,JVM為了保證每一個枚舉類元素的唯一實例,是不會允許外部進行new的,所以會把構造函數設計成private,防止用戶生成實例,破壞唯一性。

枚舉類里面含有增刪查改四種。私有的靜態類SQLStatement有sql語句的各種關鍵字list,distinct是boolean類型,例如:

   List<String> sets = new ArrayList();

子類ArrayList實例化List,因為List是一個接口,所以只能依靠其“子類”(在這里是List的實現類)來進行實例化,這里的對象是List的對象。

  private void sqlClause(AbstractSQL.SafeAppendable builder, String keyword, List<String> parts, String open, String close, String conjunction) {
            if(!parts.isEmpty()) {
                if(!builder.isEmpty()) {
                    builder.append("\n");
                }
 
                builder.append(keyword);
                builder.append(" ");
                builder.append(open);
                String last = "________";
                int i = 0;
 
                for(int n = parts.size(); i < n; ++i) {
                    String part = (String)parts.get(i);
                    if(i > 0 && !part.equals(") \nAND (") && !part.equals(") \nOR (") && !last.equals(") \nAND (") && !last.equals(") \nOR (")) {
                        builder.append(conjunction);
                    }
 
                    builder.append(part);
                    last = part;
                }
 
                builder.append(close);
            } 
        }

上面這個函數就是增刪查改通用的sql解析函數。

下面是增調用的函數

  private String insertSQL(AbstractSQL.SafeAppendable builder) {
            this.sqlClause(builder, "INSERT INTO", this.tables, "", "", "");
            this.sqlClause(builder, "", this.columns, "(", ")", ", ");
            this.sqlClause(builder, "VALUES", this.values, "(", ")", ", ");
            return builder.toString();
        }

通過下面的函數確定增刪查改對應調用的函數

 public String sql(Appendable a) {
            AbstractSQL.SafeAppendable builder = new AbstractSQL.SafeAppendable(a);
            if(this.statementType == null) {
                return null;
            } else {
                String answer;
                switch(null.$SwitchMap$org$apache$ibatis$jdbc$AbstractSQL$SQLStatement$StatementType[this.statementType.ordinal()]) {
                case 1:
                    answer = this.deleteSQL(builder);
                    break;
                case 2:
                    answer = this.insertSQL(builder);
                    break;
                case 3:
                    answer = this.selectSQL(builder);
                    break;
                case 4:
                    answer = this.updateSQL(builder);
                    break;
                default:
                    answer = null;
                }
 
                return answer;
            }
        }

私有靜態SalfAppendable類是進行sql字符串的拼接。

里面有是一個私有不可以改變的Appendable對象。

 private static class SafeAppendable {
        private final Appendable a;
        private boolean empty = true;
 
        public SafeAppendable(Appendable a) {
            this.a = a;
        }
 
        public AbstractSQL.SafeAppendable append(CharSequence s) {
            try {
                if(this.empty && s.length() > 0) {
                    this.empty = false;
                }
 
                this.a.append(s);
                return this;
            } catch (IOException var3) {
                throw new RuntimeException(var3);
            }
        }
 
        public boolean isEmpty() {
            return this.empty;
        }
    }

@InsertProvider執行的原理是什么

@InsertProvider執行的原理是什么

然后調用ProviderSqlSource類,接著調用不可變類MappedStatement類,再調用BaseStatementHandler類,--->PreparedStatementHandler等。

2.ProviderSqlSource實現了sqlSource接口

代表從注解中讀取相關的映射語句的內容,它創建的sql會被傳到數據庫。

根據SQL語句的類型不同,mybatis提供了多種SqlSource的具體實現:

1)StaticSqlSource:最終靜態SQL語句的封裝,其他類型的SqlSource最終都委托給StaticSqlSource。

2)RawSqlSource:原始靜態SQL語句的封裝,在加載時就已經確定了SQL語句,沒有、等動態標簽和${} SQL拼接,比動態SQL語句要快,因為不需要運行時解析SQL節點。

3)DynamicSqlSource:動態SQL語句的封裝,在運行時需要根據參數處理、等標簽或者${} SQL拼接之后才能生成最后要執行的靜態SQL語句。

4)ProviderSqlSource:當SQL語句通過指定的類和方法獲取時(使用@XXXProvider注解),需要使用本類,它會通過反射調用相應的方法得到SQL語句

關于@Insert和@InsertProvider注解用法

@Insert和@InsertProvider都是用來在實體類的Mapper類里注解保存方法的SQL語句。

不同的是,@Insert是直接配置SQL語句,而@InsertProvider則是通過SQL工廠類及對應的方法生產SQL語句,這種方法的好處在于,我們可以根據不同的需求生產出不同的SQL,適用性更好。

1.項目主要結構

(1)項目中的實體類

(2)每個實體類對應的Mapper方法

(3)SQL工廠

@InsertProvider執行的原理是什么

2.下面以BlogMapper中的保存Blog實體方法為例

Blog實體類屬性:

為了方便說明,屬性不設置過多,假設Blog類的屬性有blogId,title,author

(1)@Insert的注解方式

@Insert("insert into blog(blogId,title,author) values(#blogId,#title,#author)")
public boolean saveBlog(Blog blog);

說明:由于我們不能確定哪些屬性沒有值,那只能把所有屬性都寫上了。

(2)@InsertProvider的注解方式

@InsertProvider(type = SqlFactory.class,method = "insertBlog")
public boolean saveBlog(@Param("bean")Blog blog);

說明:type指明SQL工廠類,method是工廠類里對應的方法

SqlFactory類代碼:

public class SqlFactory { 
    public String insertBlog(Map<String,Object> para){ 
        Blog blog = (Blog)para.get("bean"); // 
        SQL sql = new SQL(); //SQL語句對象,所在包:org.apache.ibatis.jdbc.SQL 
        sql.INSERT_INTO("blog"); 
        if(blog.getBlogId() != null){ //判斷blogId屬性是否有值
            sql.VALUES("blogId", blog.getBlogId());
        }
 
        if(blog.getTitle() != null){//判斷title屬性是否有值
            sql.VALUES("title", blog.getTitle());
        }
 
        if(blog.getAuthor() != null){//判斷author屬性是否有值
            sql.VALUES("author", blog.getAuthor());
        } 
        return sql.toString();
} 
}

使用@InsertProvider的方式,可以根據實體中有值的屬性,進行動態的生成插入SQL語句如:

  • blogId和title有值:insert into blog(blogId,title) values(v1,v2);

  • author和title有值:insert into blog(author,title) values(v1,v2);

總結:其實也就是說因為mybaits的xml中有<if test=""></if>標簽來動態生成sql,但是在程序代碼中沒有辦法這么做。

那么insertprovider就是充當了這樣一個角色,來動態的生成sql。

與之類似的還有MyBatis注解的巧妙使用---@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider等等。

“@InsertProvider執行的原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平武县| 育儿| 大余县| 洛宁县| 乐至县| 北宁市| 宾川县| 本溪市| 泽库县| 利辛县| 西充县| 灵丘县| 建始县| 三亚市| 白山市| 长海县| 浮山县| 巨鹿县| 温宿县| 黎城县| 克拉玛依市| 阿尔山市| 忻州市| 察隅县| 白银市| 永德县| 绵阳市| 乌拉特中旗| 洪洞县| 施秉县| 东丰县| 若羌县| 奉化市| 思茅市| 张掖市| 武义县| 乌兰县| 扎兰屯市| 湘潭县| 平凉市| 旬邑县|