天天看點

mybatis

mybatis 文檔:https://mybatis.org/mybatis-3/zh/

##maven:pom.xml

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>      

 #mybatis-config.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>
<!--    可以配置兩個環境development test default=xxx-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/iqiyi?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="howhy@123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        <mapper class="com.howhy.study.mapper.UserMapper"/>-->
        <package name="com.howhy.study.mapper"/>
    </mappers>
</configuration>      
##UserMapper.java接口 UserMapper.xml 檔案名稱路徑必須一緻      
##UserMapper.java      
public interface UserMapper {

    public User findUserById(Integer id);
}      
##UserMapper.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.howhy.study.mapper.UserMapper">
<select id="findUserById" resultType="com.howhy.study.domain.User">
    select * from account where id = #{id}
  </select>
</mapper>      
##mybatis日志
##pom.xml      
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.20</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>      
##logback.xml      
<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置檔案修改時重新加載,預設true -->
<configuration scan="true">
    
    <!--定義日志檔案的存儲位址 勿在 LogBack 的配置中使用相對路徑-->
    <property name="CATALINA_BASE" value="**/logs"></property>
    
    <!-- 控制台輸出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <!-- 輸出日志記錄格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <!-- 第一個檔案輸出,每天産生一個檔案 -->
    <appender name="FILE1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 輸出檔案路徑+檔案名 -->
            <fileNamePattern>${CATALINA_BASE}/aa.%d{yyyyMMdd}.log</fileNamePattern>
            <!-- 儲存30天的日志 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <!-- 輸出日志記錄格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <!-- 第二個檔案輸出,每天産生一個檔案 -->
    <appender name="FILE2" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${CATALINA_BASE}/bb.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${CATALINA_BASE}/bb.%d{yyyyMMdd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <appender name="CUSTOM" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${CATALINA_BASE}/custom.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <fileNamePattern>${CATALINA_BASE}/custom.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- keep 30 days' worth of history -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 設定日志輸出級别 -->
    <root level="ERROR">
        <appender-ref ref="CONSOLE" />
    </root>
    <logger name="file1" level="DEBUG">
        <appender-ref ref="FILE1" />
    </logger>
    <logger name="file1" level="INFO">
        <appender-ref ref="FILE2" />
    </logger>
    <!-- 自定義logger -->
    <logger name="custom" level="INFO">
        <appender-ref ref="CUSTOM" />
    </logger>
</configuration>      

首先,如果你的資料庫支援自動生成主鍵的字段(比如 MySQL 和 SQL Server),那麼你可以設定 useGeneratedKeys=”true”,然後再把 keyProperty 設定為目标屬性就 OK 了。例如,如果上面的 Author 表已經在 id 列上使用了自動生成,那麼語句可以修改為:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>      

如果你的資料庫還支援多行插入, 你也可以傳入一個 

Author

 數組或集合,并傳回自動生成的主鍵。

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>      

對于不支援自動生成主鍵列的資料庫和可能不支援自動生成主鍵的 JDBC 驅動,MyBatis 有另外一種方法來生成主鍵。

這裡有一個簡單(也很傻)的示例,它可以生成一個随機 ID(不建議實際使用,這裡隻是為了展示 MyBatis 處理問題的靈活性和寬容度):

<insert id="insertAuthor">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
  </selectKey>
  insert into Author
    (id, username, password, email,bio, favourite_section)
  values
    (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>      

在上面的示例中,首先會運作 selectKey 元素中的語句,并設定 Author 的 id,然後才會調用插入語句。這樣就實作了資料庫自動生成主鍵類似的行為,同時保持了 Java 代碼的簡潔。

selectKey 元素描述如下:

<selectKey
  keyProperty="id"
  resultType="int"
  order="BEFORE"
  statementType="PREPARED">      

##mybatis 參數傳遞 

1、#{} jdbc預編譯的方式?傳參 可以防止sql注入   ${}  sql語句拼接的方式 有sql注入問題 一個參數 #{這裡可以随便寫} ${這裡可以随便寫} 

2、多個參數:#{arg0} #{arg1}  或 #{param1} #{param2}   若dao層 參數沒有注解@Param() 這兩個方式都可以 若有注解@Param()隻能使用#{param1} #{param2}

3、參數是javaBean或map  單個參數可以直接使用#{屬性名} 或#{param1} 多個參數可以使用:#{param1}  #{bean.屬性} #{param1.屬性} 

4、參數是集合或數組  mybatis list會封閉成map {key:"list",value:"[1,2]"}   數組會封裝成map {key:"array",value:"[1,2]"}如下 

<select id="findUserByIds" resultType="com.howhy.study.domain.User">
    select * from account where id = #{list[0]} or id = #{list[1]}
  </select>      
<select id="findUserByIds" resultType="com.howhy.study.domain.User">
    select * from account where id = #{array[0]} or id = #{array[1]}
  </select>      

##ResultMap

<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap>
然後在引用它的語句中設定 resultMap 屬性就行了(注意我們去掉了 resultType 屬性)。比如:

<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>      

 Mybatis緩存

一級緩存:預設開啟了

  1、若關閉:localCacheScope=STATEMENT

  2、緩存預設作用域是基于sqlSession的,一次資料庫操作會話

  3、緩存預設實作類PerpetualCache,使用map進行存儲的key的值是hashcode+sqlid+sql語句+hashcode+開發環境

       4、查詢時就會緩存

  緩存失效的情況:

  1、不同的sqlSession會使一級緩存失效

  2、同一個sqlSession不同的sql查詢語句

  3、同一個sqlSession和同樣的sql查詢語句但執行了其它的增删改的情況

  4、手動清空緩存

二級緩存:預設也是開啟的,但沒有實作

   1、作用域是全局的,應用級的

   2、開啟二級緩存 :<setting name="cacheEnabled" value="true"></setting>

   3、在需要用到二級緩存的映射檔案mapper.xml中加入<cache></cache>,基于mapper映射檔案來實作緩存的,基于mapper映射檔案命名空間來存儲的

   4、事務送出時才會緩存

        緩存失效:

   1、同一個命名空間進行增删改就會失效

  先從二級緩存中取 若二級緩存沒有再從一級緩存中取