一、MyBatis動(dòng)態(tài)SQL
動(dòng)態(tài) SQL 是 MyBatis 的強(qiáng)大特性之一兴泥。如果你使用過(guò) JDBC 或其它類(lèi)似的框架工育,你應(yīng)該能理解根據(jù)不同條件拼接 SQL 語(yǔ)句有多痛苦,例如拼接時(shí)要確保不能忘記添加必要的空格搓彻,還要注意去掉列表最后一個(gè)列名的逗號(hào)如绸。利用動(dòng)態(tài) SQL,可以徹底擺脫這種痛苦旭贬。
使用動(dòng)態(tài) SQL 并非一件易事怔接,但借助可用于任何 SQL 映射語(yǔ)句中的強(qiáng)大的動(dòng)態(tài) SQL 語(yǔ)言,MyBatis 顯著地提升了這一特性的易用性稀轨。
-
如果你之前用過(guò) JSTL 或任何基于類(lèi) XML 語(yǔ)言的文本處理器扼脐,你對(duì)動(dòng)態(tài) SQL 元素可能會(huì)感覺(jué)似曾相識(shí)。在 MyBatis 之前的版本中奋刽,需要花時(shí)間了解大量的元素瓦侮。借助功能強(qiáng)大的基于 OGNL 的表達(dá)式,MyBatis 3 替換了之前的大部分元素佣谐,大大精簡(jiǎn)了元素種類(lèi)肚吏,現(xiàn)在要學(xué)習(xí)的元素種類(lèi)比原來(lái)的一半還要少。
if
- 使用動(dòng)態(tài) SQL 最常見(jiàn)情景是根據(jù)條件包含 where 子句的一部分狭魂。比如:
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
- 這條語(yǔ)句提供了可選的查找文本功能罚攀。如果不傳入 “title”吁断,那么所有處于 “ACTIVE” 狀態(tài)的 BLOG 都會(huì)返回;如果傳入了 “title” 參數(shù)坞生,那么就會(huì)對(duì) “title” 一列進(jìn)行模糊查找并返回對(duì)應(yīng)的 BLOG 結(jié)果仔役。
- 通過(guò) “title” 和 “author” 兩個(gè)參數(shù)進(jìn)行可選搜索,只需要加入另一個(gè)條件即可是己。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
choose又兵、when、otherwise
- MyBatis 提供了 choose 元素卒废,它有點(diǎn)像 Java 中的 switch 語(yǔ)句沛厨。傳入了 “title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形摔认。若兩者都沒(méi)有傳入逆皮,就返回標(biāo)記為 featured 的 BLOG。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
trim参袱、where电谣、set
- 將 “state = ‘ACTIVE’” 設(shè)置成動(dòng)態(tài)條件。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
- 如果沒(méi)有匹配的條件抹蚀,最終這條 SQL 會(huì)變成這樣:SELECT * FROM BLOG WHERE剿牺,這會(huì)導(dǎo)致查詢(xún)失敗。如果匹配的只是第二個(gè)條件环壤,這條 SQL 會(huì)是這樣:
SELECT * FROM BLOG WHERE AND title like ‘someTitle’晒来,這個(gè)查詢(xún)也會(huì)失敗。 - MyBatis 有一個(gè)簡(jiǎn)單且適合大多數(shù)場(chǎng)景的解決辦法郑现。而在其他場(chǎng)景中湃崩,可以對(duì)其進(jìn)行自定義以符合需求。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
- where 元素只會(huì)在子元素返回任何內(nèi)容的情況下才插入 “WHERE” 子句接箫。而且攒读,若子句的開(kāi)頭為 “AND” 或 “OR”,where 元素也會(huì)將它們?nèi)コ形H绻?where 元素與你期望的不太一樣整陌,你也可以通過(guò)自定義 trim 元素來(lái)定制 where 元素的功能。
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
- prefixOverrides 屬性會(huì)忽略通過(guò)管道符分隔的文本序列瞎领。上述例子會(huì)移除所有 prefixOverrides 屬性中指定的內(nèi)容,并且插入 prefix 屬性中指定的內(nèi)容随夸。用于動(dòng)態(tài)更新語(yǔ)句的類(lèi)似解決方案叫做 set九默。set 元素可以用于動(dòng)態(tài)包含需要更新的列,忽略其它不更新的列宾毒。
<update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null"> username=#{username}, </if> <if test="password != null"> password=#{password}, </if> <if test="email != null"> email=#{email}, </if> <if test="bio != null"> bio=#{bio} </if> </set> where id=#{id} </update>
- 與 set 元素等價(jià)的自定義 trim 元素
<trim prefix="SET" suffixOverrides=","> ... </trim>
foreach
- 動(dòng)態(tài) SQL 的另一個(gè)常見(jiàn)使用場(chǎng)景是對(duì)集合進(jìn)行遍歷(尤其是在構(gòu)建 IN 條件語(yǔ)句的時(shí)候)驼修。
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
- foreach 元素的功能非常強(qiáng)大,它允許你指定一個(gè)集合,聲明可以在元素體內(nèi)使用的集合項(xiàng)(item)和索引(index)變量乙各。它也允許你指定開(kāi)頭與結(jié)尾的字符串以及集合項(xiàng)迭代之間的分隔符墨礁。
script
- 要在帶注解的映射器接口類(lèi)中使用動(dòng)態(tài) SQL,可以使用 script 元素耳峦。
@Update({"<script>", "update Author", " <set>", " <if test='username != null'>username=#{username},</if>", " <if test='password != null'>password=#{password},</if>", " <if test='email != null'>email=#{email},</if>", " <if test='bio != null'>bio=#{bio}</if>", " </set>", "where id=#{id}", "</script>"}) void updateAuthorValues(Author author);
bind
- bind 元素允許你在 OGNL 表達(dá)式以外創(chuàng)建一個(gè)變量恩静,并將其綁定到當(dāng)前的上下文。
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select>
多數(shù)據(jù)庫(kù)支持
- 如果配置了 databaseIdProvider蹲坷,你就可以在動(dòng)態(tài)代碼中使用名為 “_databaseId” 的變量來(lái)為不同的數(shù)據(jù)庫(kù)構(gòu)建特定的語(yǔ)句驶乾。
<insert id="insert"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> <if test="_databaseId == 'oracle'"> select seq_users.nextval from dual </if> <if test="_databaseId == 'db2'"> select nextval for seq_users from sysibm.sysdummy1" </if> </selectKey> insert into users values (#{id}, #{name}) </insert>
動(dòng)態(tài) SQL 中的插入腳本語(yǔ)言
- MyBatis 從 3.2 版本開(kāi)始支持插入腳本語(yǔ)言,這允許你插入一種語(yǔ)言驅(qū)動(dòng)循签,并基于這種語(yǔ)言來(lái)編寫(xiě)動(dòng)態(tài) SQL 查詢(xún)語(yǔ)句级乐。
public interface LanguageDriver { ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql); SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType); SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType); }
- 實(shí)現(xiàn)自定義語(yǔ)言驅(qū)動(dòng)后,你就可以在 mybatis-config.xml 文件中將它設(shè)置為默認(rèn)語(yǔ)言:
<typeAliases> <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/> </typeAliases> <settings> <setting name="defaultScriptingLanguage" value="myLanguage"/> </settings>
- 你也可以使用 lang 屬性為特定的語(yǔ)句指定語(yǔ)言:
<select id="selectBlog" lang="myLanguage"> SELECT * FROM BLOG </select>
- 在你的 mapper 接口上添加 @Lang 注解:
public interface Mapper { @Lang(MyLanguageDriver.class) @Select("SELECT * FROM BLOG") List<Blog> selectBlog(); }
- 使用動(dòng)態(tài) SQL 最常見(jiàn)情景是根據(jù)條件包含 where 子句的一部分狭魂。比如:
二县匠、MyBatis緩存
默認(rèn)情況下风科,只啟用了本地的會(huì)話(huà)緩存(SqlSession),它僅僅對(duì)一個(gè)會(huì)話(huà)中的數(shù)據(jù)進(jìn)行緩存乞旦,會(huì)話(huà)緩存也稱(chēng)為一級(jí)緩存丐重。二級(jí)緩存是全局緩存(SqlSessionFactory),需要手動(dòng)開(kāi)啟:在SQL映射文件中添加一行:<cache/>
-
緩存的清除策略:
- LRU(Least Recently Uses):最近最少使用杆查,移除最長(zhǎng)時(shí)間不被使用的對(duì)象
- FIFO(First In First Out):先進(jìn)先出扮惦,按照對(duì)象進(jìn)入緩存的順序來(lái)移除他們。這也是數(shù)據(jù)結(jié)構(gòu)中隊(duì)列(Queue)的元素存取方式亲桦。
- SOFT:軟引用崖蜜,基于來(lái)及回收器狀態(tài)和軟引用規(guī)則移除對(duì)象
- WEAK:弱引用,更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則來(lái)移除對(duì)象
默認(rèn)的清除策略是LRU
三客峭、日志 log4j
- Mybatis 通過(guò)使用內(nèi)置的日志工廠提供日志功能豫领。內(nèi)置日志工廠將會(huì)把日志工作委托給下面的實(shí)現(xiàn)之一:
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j
- JDK logging
- MyBatis 內(nèi)置日志工廠會(huì)基于運(yùn)行時(shí)檢測(cè)信息選擇日志委托實(shí)現(xiàn)。它會(huì)(按上面羅列的順序)使用第一個(gè)查找到的實(shí)現(xiàn)舔琅。當(dāng)沒(méi)有找到這些實(shí)現(xiàn)時(shí)等恐,將會(huì)禁用日志功能。
- 可以在mybatis配置文件中設(shè)置日志選項(xiàng)备蚓,可選的值有:SLF4J课蔬、LOG4J、LOG4J2郊尝、JDK_LOGGING二跋、COMMONS_LOGGING、STDOUT_LOGGING流昏、NO_LOGGING扎即,或者是實(shí)現(xiàn)了 org.apache.ibatis.logging.Log 接口吞获,且構(gòu)造方法以字符串為參數(shù)的類(lèi)完全限定名。
- 全局日志配置可以配置打印的日志級(jí)別谚鄙,日志的輸出對(duì)象各拷。日志的四個(gè)級(jí)別:error、warn闷营、info烤黍、debug,優(yōu)先級(jí)從高到低粮坞;如果設(shè)置為error蚊荣,只打印error信息,如果設(shè)置為debug莫杈,所有級(jí)別的信息都會(huì)打踊ダ;只會(huì)打印大于等于這個(gè)級(jí)別的日志筝闹。stdout是標(biāo)準(zhǔn)輸出:打印在控制臺(tái)媳叨。還可以將日志輸出到文件,最后一行指定了最小輸出寬度以及對(duì)齊方式关顷。
- MyBatis日志配置設(shè)置了跟蹤的包糊秆、類(lèi)或方法,對(duì)特定包下的類(lèi)议双、特定類(lèi)痘番、特定方法才會(huì)打印日志。
四平痰、測(cè)試動(dòng)態(tài)SQL和日志log4j
-
添加junit汞舱,mysql,mybatis 以及 log4j 的依賴(lài)到 pom.xml 中
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>MyBatisSQL</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
-
Mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="db.properties"> </properties> <settings> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <package name="com.pojo" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${user}"/> <property name="password" value="${pass}"/> </dataSource> </environment> </environments> <mappers> <package name="com.pojo" /> </mappers> </configuration>
-
db.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3307/mysqls?serverTimezone=UTC user=root pass=123456
-
log4j.properties
log4j.rootLogger=debug, stdout, F # MyBatis 日志配置 log4j.logger.com.qfedu=TRACE # 控制臺(tái)輸出 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%6p [%t] - %m%n log4j.appender.F = org.apache.log4j.DailyRollingFileAppender log4j.appender.F.File =myproj.log log4j.appender.F.Append = true log4j.appender.F.Threshold = DEBUG log4j.appender.F.layout=org.apache.log4j.PatternLayout log4j.appender.F.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss}-[%p %F\:%L] %m%n
-
User.java
@Data @NoArgsConstructor @AllArgsConstructor public class User { private int uid; private String username; private String password; private int age; private String addr; }
-
IUserDao.java
public interface IUserDao { @Select("select * from user") List<User> getAll(); }
-
IUserDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.pojo.IUserDao"> <sql id="all"> select * from user </sql> <select id="selectAll" resultType="user"> <include refid="all"/> </select> <select id="selectUserByUid" resultType="user"> <include refid="all"/> where uid = #{uid} </select> <select id="selectIf" resultType="user"> <include refid="all"/> <where> <if test="username != null"> username = #{username} </if> <if test="password != null"> and password = #{password} </if> </where> </select> <select id="selectIn" resultType="user"> <include refid="all" /> <where> uid in <foreach collection="ids" item="id" index="index" open="(" close=")" separator=","> #{id} </foreach> </where> </select> </mapper>
-
SessionUtils.java
public class SessionUtils { private static SqlSession mSession = null; private static SqlSessionFactory mFactory = null; static { try { mFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml")); } catch (IOException e) { e.printStackTrace(); } } /** * 獲取SqlSession對(duì)象 * @return */ public static SqlSession getSession(){ mSession = mFactory.openSession(true); return mSession; } /** * 關(guān)閉SqlSession對(duì)象 * @param session 要關(guān)閉的SqlSession對(duì)象 */ public static void closeSession(SqlSession session){ if(session != null){ session.close(); session = null; } } }
-
TestLog.java
public class TestLog { private SqlSession session = null; @Before public void setUp() { session = SessionUtils.getSession(); } @After public void tearDown() { SessionUtils.closeSession(session); } @Test public void testLog(){ IUserDao userDao = session.getMapper(IUserDao.class); List<User> list = userDao.getAll(); for (User u : list) { System.out.println(u); } } }
-
測(cè)試結(jié)果
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. DEBUG [main] - Class not found: org.jboss.vfs.VFS DEBUG [main] - JBoss 6 VFS API is not available in this environment. DEBUG [main] - Class not found: org.jboss.vfs.VirtualFile DEBUG [main] - VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment. DEBUG [main] - Using VFS adapter org.apache.ibatis.io.DefaultVFS DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Reader entry: IUserDao.class DEBUG [main] - Reader entry: User.class DEBUG [main] - Listing file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Reader entry: ???? 4 ?? DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Reader entry: ???? 4 n ? Q ? R ? S ? T ? U? V DEBUG [main] - Checking to see if class com.pojo.IUserDao matches criteria [is assignable to Object] DEBUG [main] - Checking to see if class com.pojo.User matches criteria [is assignable to Object] DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Reader entry: IUserDao.class DEBUG [main] - Reader entry: User.class DEBUG [main] - Listing file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Reader entry: ???? 4 ?? DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Reader entry: ???? 4 n ? Q ? R ? S ? T ? U? V DEBUG [main] - Checking to see if class com.pojo.IUserDao matches criteria [is assignable to Object] DEBUG [main] - Checking to see if class com.pojo.User matches criteria [is assignable to Object] DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 2030538903. DEBUG [main] - ==> Preparing: select * from user DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 13 User(uid=1, username=aaa, password=111111, age=10, addr=aaaa) User(uid=2, username=bbb, password=222222, age=11, addr=aaaa) User(uid=3, username=ccc, password=333333, age=12, addr=aaaa) User(uid=4, username=ddd, password=444444, age=13, addr=aaaa) User(uid=5, username=eee, password=555555, age=14, addr=aaaa) User(uid=6, username=fff, password=666666, age=15, addr=aaaa) User(uid=7, username=ggg, password=777777, age=16, addr=aaaa) User(uid=8, username=hhh, password=888888, age=17, addr=aaaa) User(uid=9, username=iii, password=999999, age=18, addr=aaaa) User(uid=10, username=jjj, password=000000, age=19, addr=aaaa) User(uid=11, username=kkk, password=000000, age=20, addr=aaaa) User(uid=12, username=lkt, password=888888, age=20, addr=suzhou) User(uid=15, username=ABC, password=111111, age=20, addr=南京) DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79079097] DEBUG [main] - Returned connection 2030538903 to pool.
-
TestUserSQL.java
public class TestUserSQL { private SqlSession session = null; @Before public void setUp() { session = SessionUtils.getSession(); } @After public void tearDown() { SessionUtils.closeSession(session); } @Test public void testGetAllUsers() { List<User> list = session.selectList("com.pojo.IUserDao.selectAll"); for (User u : list) { System.out.println(u); } } @Test public void testGetAllUsersByUid() { User u = session.selectOne("com.pojo.IUserDao.selectUserByUid", 1); System.out.println(u); } @Test public void testGetUserByIf(){ Map<String, Object> map = new HashMap<>(); map.put("password", "333333"); List<User> list = session.selectList("com.pojo.IUserDao.selectIf", map); for (User u : list) { System.out.println(u); } } @Test public void testGetUsersByIn(){ List<Integer> ids = new ArrayList<>(); Collections.addAll(ids, 1, 2, 3, 4, 100); System.out.println(ids); Map<String, Object> map = new HashMap<>(); map.put("ids", ids); List<User> list = session.selectList("com.pojo.IUserDao.selectIn", map); for (User u : list) { System.out.println(u); } } }
-
測(cè)試結(jié)果
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. DEBUG [main] - Class not found: org.jboss.vfs.VFS DEBUG [main] - JBoss 6 VFS API is not available in this environment. DEBUG [main] - Class not found: org.jboss.vfs.VirtualFile DEBUG [main] - VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment. DEBUG [main] - Using VFS adapter org.apache.ibatis.io.DefaultVFS DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Reader entry: IUserDao.class DEBUG [main] - Reader entry: IUserDao.xml DEBUG [main] - Reader entry: User.class DEBUG [main] - Listing file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Reader entry: ???? 4 ?? DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.xml DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.xml DEBUG [main] - Reader entry: <?xml version="1.0" encoding="UTF-8" ?> DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Reader entry: ???? 4 n ? Q ? R ? S ? T ? U? V DEBUG [main] - Checking to see if class com.pojo.IUserDao matches criteria [is assignable to Object] DEBUG [main] - Checking to see if class com.pojo.User matches criteria [is assignable to Object] DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Reader entry: IUserDao.class DEBUG [main] - Reader entry: IUserDao.xml DEBUG [main] - Reader entry: User.class DEBUG [main] - Listing file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.class DEBUG [main] - Reader entry: ???? 4 ?? DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.xml DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/IUserDao.xml DEBUG [main] - Reader entry: <?xml version="1.0" encoding="UTF-8" ?> DEBUG [main] - Find JAR URL: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Not a JAR: file:/F:/IDEA-Work/MyBatisSQLAndLog4J/target/classes/com/pojo/User.class DEBUG [main] - Reader entry: ???? 4 n ? Q ? R ? S ? T ? U? V DEBUG [main] - Checking to see if class com.pojo.IUserDao matches criteria [is assignable to Object] DEBUG [main] - Checking to see if class com.pojo.User matches criteria [is assignable to Object] DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 515715487. DEBUG [main] - ==> Preparing: select * from user DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 13 User(uid=1, username=aaa, password=111111, age=10, addr=aaaa) User(uid=2, username=bbb, password=222222, age=11, addr=aaaa) User(uid=3, username=ccc, password=333333, age=12, addr=aaaa) User(uid=4, username=ddd, password=444444, age=13, addr=aaaa) User(uid=5, username=eee, password=555555, age=14, addr=aaaa) User(uid=6, username=fff, password=666666, age=15, addr=aaaa) User(uid=7, username=ggg, password=777777, age=16, addr=aaaa) User(uid=8, username=hhh, password=888888, age=17, addr=aaaa) User(uid=9, username=iii, password=999999, age=18, addr=aaaa) User(uid=10, username=jjj, password=000000, age=19, addr=aaaa) User(uid=11, username=kkk, password=000000, age=20, addr=aaaa) User(uid=12, username=lkt, password=888888, age=20, addr=suzhou) User(uid=15, username=ABC, password=111111, age=20, addr=南京) DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1ebd319f] DEBUG [main] - Returned connection 515715487 to pool. DEBUG [main] - Opening JDBC Connection DEBUG [main] - Checked out connection 515715487 from pool. DEBUG [main] - ==> Preparing: select * from user where uid = ? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - <== Total: 1 User(uid=1, username=aaa, password=111111, age=10, addr=aaaa) DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1ebd319f] DEBUG [main] - Returned connection 515715487 to pool. DEBUG [main] - Opening JDBC Connection DEBUG [main] - Checked out connection 515715487 from pool. DEBUG [main] - ==> Preparing: select * from user WHERE password = ? DEBUG [main] - ==> Parameters: 333333(String) DEBUG [main] - <== Total: 1 User(uid=3, username=ccc, password=333333, age=12, addr=aaaa) DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1ebd319f] DEBUG [main] - Returned connection 515715487 to pool. [1, 2, 3, 4, 100] DEBUG [main] - Opening JDBC Connection DEBUG [main] - Checked out connection 515715487 from pool. DEBUG [main] - ==> Preparing: select * from user WHERE uid in ( ? , ? , ? , ? , ? ) DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer), 3(Integer), 4(Integer), 100(Integer) DEBUG [main] - <== Total: 4 User(uid=1, username=aaa, password=111111, age=10, addr=aaaa) User(uid=2, username=bbb, password=222222, age=11, addr=aaaa) User(uid=3, username=ccc, password=333333, age=12, addr=aaaa) User(uid=4, username=ddd, password=444444, age=13, addr=aaaa) DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1ebd319f] DEBUG [main] - Returned connection 515715487 to pool.
五宗雇、Mybatis的SQL語(yǔ)句構(gòu)造器
- MyBatis 3 提供了方便的工具類(lèi)來(lái)幫助解決該問(wèn)題昂芜。使用SQL類(lèi),簡(jiǎn)單地創(chuàng)建一個(gè)實(shí)例來(lái)調(diào)用方法生成SQL語(yǔ)句赔蒲。
- SQL 語(yǔ)句生成器列表
方法 | 描述 |
---|---|
SELECT(字串) SELECT(字符串...)
|
開(kāi)始或插入到選擇子句泌神。可以被多次調(diào)用舞虱,參數(shù)也會(huì)添加到SELECT 子句欢际。參數(shù)通常使用逗號(hào)分隔的列名和別名列表,但也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類(lèi)型砾嫉。 |
SELECT_DISTINCT(字符串) SELECT_DISTINCT(字符串...)
|
開(kāi)始或插入到SELECT 子句幼苛,也可以插入DISTINCT 關(guān)鍵字到生成的查詢(xún)語(yǔ)句中』拦危可以被多次調(diào)用舶沿,參數(shù)也會(huì)添加到SELECT 子句。參數(shù)通常使用逗號(hào)分隔的列名和別名列表配并,但也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類(lèi)型括荡。 |
FROM(字符串) FROM(字符串...)
|
開(kāi)始或插入到FROM 子句「刃可以被多次調(diào)用畸冲,參數(shù)也會(huì)添加到FROM 子句。參數(shù)通常是表名或別名观腊,也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類(lèi)型邑闲。 |
JOIN(字符串) JOIN(字符串...) INNER_JOIN(字符串) INNER_JOIN(字符串...) LEFT_OUTER_JOIN(字符串) LEFT_OUTER_JOIN(字符串...) RIGHT_OUTER_JOIN(字符串) RIGHT_OUTER_JOIN(字符串...)
|
基于調(diào)用的方法,添加新的合適類(lèi)型的JOIN 子句梧油。參數(shù)可以包含由列命和加入的條件組合成標(biāo)準(zhǔn)的加入苫耸。 |
WHERE(String) WHERE(String...)
|
插入新的 WHERE 子句條件, 由AND 鏈接儡陨⊥首樱可以多次被調(diào)用,每次都由AND 來(lái)鏈接新條件骗村。使用 OR() 來(lái)分隔OR 嫌褪。 |
OR() |
使用OR 來(lái)分隔當(dāng)前的 WHERE 子句條件。 可以被多次調(diào)用胚股,但在一行中多次調(diào)用或生成不穩(wěn)定的SQL 笼痛。 |
AND() |
使用AND 來(lái)分隔當(dāng)前的 WHERE 子句條件。 可以被多次調(diào)用琅拌,但在一行中多次調(diào)用或生成不穩(wěn)定的SQL 缨伊。因?yàn)?WHERE 和 HAVING 二者都會(huì)自動(dòng)鏈接 AND , 這是非常罕見(jiàn)的方法,只是為了完整性才被使用财忽。 |
GROUP_BY(String) GROUP_BY(String...)
|
插入新的 GROUP BY 子句元素倘核,由逗號(hào)連接。 可以被多次調(diào)用即彪,每次都由逗號(hào)連接新的條件紧唱。 |
HAVING(String) HAVING(String...)
|
插入新的 HAVING 子句條件。 由AND 連接隶校÷┮妫可以被多次調(diào)用,每次都由AND 來(lái)連接新的條件深胳。使用 OR() 來(lái)分隔OR 绰疤。 |
ORDER_BY(String) ORDER_BY(String...)
|
插入新的 ORDER BY 子句元素, 由逗號(hào)連接舞终∏崆欤可以多次被調(diào)用癣猾,每次由逗號(hào)連接新的條件。 |
LIMIT(String) LIMIT(int)
|
附加一個(gè)LIMIT 子句余爆。與SELECT( )纷宇,UPDATE() 和DELETE() 一起使用時(shí),此方法有效蛾方。并且此方法設(shè)計(jì)為在使用SELECT() 時(shí)與OFFSET() 一起使用像捶。 |
OFFSET(String) OFFSET(long)
|
附加一個(gè)OFFSET 子句。與SELECT() 一起使用時(shí)桩砰,此方法有效拓春。該方法設(shè)計(jì)為與LIMIT() 一起使用。 |
OFFSET_ROWS(String) OFFSET_ROWS(long)
|
附加一個(gè)OFFSET n ROWS 子句亚隅。與SELECT() 一起使用時(shí)硼莽,此方法有效。該方法旨在與FETCH_FIRST_ROWS_ONLY() 一起使用 |
FETCH_FIRST_ROWS_ONLY(String) FETCH_FIRST_ROWS_ONLY(int)
|
追加FETCH FIRST n ROWS ONLY 子句枢步。與SELECT() 一起使用時(shí)沉删,此方法有效。此方法設(shè)計(jì)為與OFFSET_ROWS() 一起使用醉途。 |
DELETE_FROM(String) |
開(kāi)始一個(gè)delete 語(yǔ)句并指定需要從哪個(gè)表刪除的表名矾瑰。通常它后面都會(huì)跟著WHERE 語(yǔ)句 |
INSERT_INTO(String) |
開(kāi)始一個(gè)insert語(yǔ)句并指定需要插入數(shù)據(jù)的表名。后面都會(huì)跟著一個(gè)或者多個(gè)VALUES() or INTO_COLUMNS() and INTO_VALUES() 隘擎。 |
SET(String) SET(String...)
|
針對(duì)update 語(yǔ)句殴穴,插入到"set "列表中 |
UPDATE(String) |
開(kāi)始一個(gè)update 語(yǔ)句并指定需要更新的表明。后面都會(huì)跟著一個(gè)或者多個(gè)SET() 货葬,通常也會(huì)有一個(gè)WHERE() 采幌。 |
VALUES(String, String) |
插入到insert語(yǔ)句中。第一個(gè)參數(shù)是要插入的列名震桶,第二個(gè)參數(shù)則是該列的值休傍。 |
INTO_COLUMNS(String...) |
插入語(yǔ)句的形式是:INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)
|
INTO_VALUES(String...) |
插入語(yǔ)句的形式是:INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)
|
ADD_ROW() |
為批量插入添加新行。 |