Mybatis3 SQL執(zhí)行進(jìn)行曲

組裝SQL

mybatis中提供了一個SQL類可以支持方便的寫sql語句郎哭。如:下方new的SQL對象以及輸出語句

  private static SQL example1() {
    return new SQL() {{
      SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
      SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
      FROM("PERSON P");
      FROM("ACCOUNT A");
      INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
      INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
      WHERE("P.ID = A.ID");
      WHERE("P.FIRST_NAME like ?");
      OR();
      WHERE("P.LAST_NAME like ?");
      GROUP_BY("P.ID");
      HAVING("P.LAST_NAME like ?");
      OR();
      HAVING("P.FIRST_NAME like ?");
      ORDER_BY("P.ID");
      ORDER_BY("P.FULL_NAME");
    }};
  }

  public static void main(String[] args) {
    System.out.println(example1().toString());
  }

SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON
FROM PERSON P, ACCOUNT A
INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID
INNER JOIN COMPANY C on D.COMPANY_ID = C.ID
WHERE (P.ID = A.ID AND P.FIRST_NAME like ?)
OR (P.LAST_NAME like ?)
GROUP BY P.ID
HAVING (P.LAST_NAME like ?)
OR (P.FIRST_NAME like ?)
ORDER BY P.ID, P.FULL_NAME

SQL對象繼承AbstractSQL夸研,AbstractSQL底層主要是一個內(nèi)部靜態(tài)類SQLStatement依鸥,SQLStatement提供了相關(guān)的sql拼裝實現(xiàn)方法,以select為例:

public T SELECT(String columns) {
    //寫入通用類型
    sql().statementType = SQLStatement.StatementType.SELECT;
    //將對應(yīng)的查詢列表寫入公共list中
    sql().select.add(columns);
    return getSelf();
  }

public String sql(Appendable a) {
      SafeAppendable builder = new SafeAppendable(a);
      if (statementType == null) {
        return null;
      }
      String answer;
      //根據(jù)上述對應(yīng)的statementType判斷調(diào)用哪個方法
      switch (statementType) {
        case DELETE:
          answer = deleteSQL(builder);
          break;
        case INSERT:
          answer = insertSQL(builder);
          break;
        case SELECT:
          answer = selectSQL(builder);
          break;
        case UPDATE:
          answer = updateSQL(builder);
          break;
        default:
          answer = null;
      }
      return answer;
    }
   //根據(jù)實際調(diào)用方法拼裝語句    
   private String selectSQL(SafeAppendable builder) {
      if (distinct) {
        sqlClause(builder, "SELECT DISTINCT", select, "", "", ", ");
      } else {
        sqlClause(builder, "SELECT", select, "", "", ", ");
      }
     sqlClause(builder, "FROM", tables, "", "", ", ");
      joins(builder);
      //拼裝關(guān)鍵詞"WHERE" + "(" + 循環(huán)條件 +"AND" +")"   
      sqlClause(builder, "WHERE", where, "(", ")", " AND ");
      sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
      sqlClause(builder, "HAVING", having, "(", ")", " AND ");
      sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
      limitingRowsStrategy.appendClause(builder, offset, limit);
      return builder.toString();
    }

創(chuàng)建Connection

MysqlDataSource ds = new MysqlDataSource();
Connection conn = ds.getConnection("username", "pwd");

ONE--調(diào)用ScriptRunner

Reader reader = Resources.getResourceAsReader(example1().toString());
ScriptRunner sr = new ScriptRunner(conn);
sr.runScript(reader);
ScriptRunner
  1. 執(zhí)行方法
public void runScript(Reader reader) {
    //調(diào)用setAutoCommit()方法,根據(jù)autoCommit屬性的值設(shè)置事務(wù)是否自動提交
    setAutoCommit();
    try {
      //判斷sendFullScript屬性值
      if (sendFullScript) {
        //如果值為true茶敏,調(diào)用executeFullScript()方法讀取SQL腳本文件的所有內(nèi)容缚俏,然后調(diào)用JDBC中Statement的execute()方法一次性執(zhí)行腳本中的所有SQL語句
        executeFullScript(reader);
      } else {
        //如果值為false忧换,調(diào)用executeLineByLine()方法逐行讀取SQL腳本文件,以分號作為每條SQL語句結(jié)束的標(biāo)志亚茬,逐條執(zhí)行SQL語句
        executeLineByLine(reader);
      }
    } finally {
      rollbackConnection();
    }
  }
  1. 一次性執(zhí)行所有sql內(nèi)容
private void executeFullScript(Reader reader) {
    StringBuilder script = new StringBuilder();
    try {
      BufferedReader lineReader = new BufferedReader(reader);
      String line;
      while ((line = lineReader.readLine()) != null) {
        script.append(line);
        script.append(LINE_SEPARATOR);
      }
      String command = script.toString();
      println(command);
      //1.創(chuàng)建Statement 2.調(diào)用JDBC中Statement的execute()方法執(zhí)行腳本中的所有SQL語句 3.根據(jù)返回的result
      executeStatement(command);
      commitConnection();
    } catch (Exception e) {
      String message = "Error executing: " + script + ".  Cause: " + e;
      printlnError(message);
      throw new RuntimeSqlException(message, e);
    }
  }
  1. 分行執(zhí)行相關(guān)sql
  private void executeLineByLine(Reader reader) {
    StringBuilder command = new StringBuilder();
    try {
      BufferedReader lineReader = new BufferedReader(reader);
      String line;
      while ((line = lineReader.readLine()) != null) {
        //按行讀取葡兑,判斷是否執(zhí)行
        handleLine(command, line);
      }
      commitConnection();
      checkForMissingLineTerminator(command);
    } catch (Exception e) {
      String message = "Error executing: " + command + ".  Cause: " + e;
      printlnError(message);
      throw new RuntimeSqlException(message, e);
    }
  }
  
  private void handleLine(StringBuilder command, String line) throws SQLException {
    String trimmedLine = line.trim();
    if (lineIsComment(trimmedLine)) {
      //如果這行內(nèi)容是注釋,跳過
      Matcher matcher = DELIMITER_PATTERN.matcher(trimmedLine);
      if (matcher.find()) {
        delimiter = matcher.group(5);
      }
      println(trimmedLine);
    } else if (commandReadyToExecute(trimmedLine)) {
    // commandReadyToExecute方法判斷最后一個字符是否是分號
    //如果這行內(nèi)容最一個字符是分號吆鹤,該sql讀取完畢
    //1.創(chuàng)建Statement 2.調(diào)用JDBC中Statement的execute()方法執(zhí)行腳本中的所有SQL語句 3.根據(jù)返回的result
      command.append(line, 0, line.lastIndexOf(delimiter));
      command.append(LINE_SEPARATOR);
      println(command);
      executeStatement(command.toString());
      command.setLength(0);
    } else if (trimmedLine.length() > 0) {
    //如果最后一個字符不是分號疑务,繼續(xù)往后拼裝sql語句
      command.append(line);
      command.append(LINE_SEPARATOR);
    }
  }

TWO-- SqlRunner

調(diào)用SqlRunner也同樣可以執(zhí)行相關(guān)sql梗醇;

MysqlDataSource ds = new MysqlDataSource();
Connection conn = ds.getConnection("username", "pwd");
//調(diào)用SqlRunner.run方法
SqlRunner exec = new SqlRunner(conn);
exec.run(example1().toString());
//調(diào)用SqlRunner.selectAll方法
List<Map<String, Object>> rows = exec.selectAll("SELECT * FROM BLAH");
//通用方法
public void run(String sql) throws SQLException {
//創(chuàng)建Statement,執(zhí)行execute方法
    try (Statement stmt = connection.createStatement()) {
      stmt.execute(sql);
    }
  }
//查詢executeQuery
public List<Map<String, Object>> selectAll(String sql, Object... args) throws SQLException {
  try (PreparedStatement ps = connection.prepareStatement(sql)) {
    setParameters(ps, args);
    try (ResultSet rs = ps.executeQuery()) {
      return getResults(rs);
    }
  }
}

selectOne方法温鸽,也是調(diào)用selectAll涤垫,判斷最終返回結(jié)果是否等于1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末竟终,一起剝皮案震驚了整個濱河市统捶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌喘鸟,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異兑凿,居然都是意外死亡礼华,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門祈惶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡涩,你說我怎么就攤上這事疹蛉。” “怎么了育韩?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵闺鲸,是天一觀的道長摸恍。 經(jīng)常有香客問我,道長误墓,這世上最難降的妖魔是什么谜慌? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任莺奔,我火速辦了婚禮,結(jié)果婚禮上恼琼,老公的妹妹穿的比我還像新娘屏富。我一直安慰自己,他們只是感情好噩死,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布已维。 她就那樣靜靜地躺著已日,像睡著了一般。 火紅的嫁衣襯著肌膚如雪堂鲜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天甫恩,我揣著相機(jī)與錄音酌予,去河邊找鬼。 笑死松靡,一個胖子當(dāng)著我的面吹牛建椰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屠列,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼笛洛,長吁一口氣:“原來是場噩夢啊……” “哼乃坤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起狱杰,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤厅须,失蹤者是張志新(化名)和其女友劉穎朗和,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體例隆,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡镀层,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吴侦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡劫樟,死狀恐怖织堂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情易阳,我是刑警寧澤潦俺,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站早像,受9級特大地震影響肖爵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜法挨,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一幅聘、第九天 我趴在偏房一處隱蔽的房頂上張望帝蒿。 院中可真熱鬧,春花似錦巷怜、人聲如沸葛超。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绣张。三九已至,卻和暖如春关带,著一層夾襖步出監(jiān)牢的瞬間侥涵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留芜飘,地道東北人务豺。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像嗦明,于是被迫代替她去往敵國和親笼沥。 傳聞我的和親對象是個殘疾皇子娶牌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1 問題 Java 程序員面對的最痛苦的事情之一就是在 Java 代碼中嵌入 SQL 語句奔浅。 如你所見,MyBat...
    大強(qiáng)博客閱讀 280評論 0 0
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,709評論 0 44
  • 基礎(chǔ)查詢 select 查詢列表 from 表名; USE myemployees; //最好寫上 1.查詢表中的...
    曖莓悠閱讀 579評論 0 1
  • 數(shù)據(jù)庫的相關(guān)概念 數(shù)據(jù)庫的好處 1诗良、持久化數(shù)據(jù)到本地2乘凸、可以實現(xiàn)結(jié)構(gòu)化查詢,方便管理 數(shù)據(jù)庫的常見概念☆ 1累榜、DB...
    lzh_1閱讀 576評論 0 3
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月营勤,有人笑有人哭,有人歡樂有人憂愁壹罚,有人驚喜有人失落葛作,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,528評論 28 53