1. 程式人生 > 實用技巧 >洛谷 P1004 方格取數(DP)

洛谷 P1004 方格取數(DP)

其實Javaweb就想直接加在裡面但,感覺不全面就算了吧.....

首先為什麼使用Mybatis?

在沒有mybatis前,java連線資料庫和寫sql語句是怎麼樣的?!

public class IStudentDaoImpl implements IStudentDao {

    private Connection conn=null;
    private PreparedStatement pst=null;
    private ResultSet rs=null;

    /**
     * 通過ID執行單個查詢
     * @param i
     * @return
*/ @Override public List<Student> selectOne(long i) { List<Student> list = new ArrayList<>(); // 查詢表中所有資料 String sql="Select * FROM student where id=?"; try { conn = JDBCUtil.getConnection(); // 預編譯語句 pst = conn.prepareStatement(sql); pst.setLong(
1,i); // 執行DDL操作 rs = pst.executeQuery(); list = JDBCUtil.loopSet(rs); } catch (SQLException throwables) { throwables.printStackTrace(); }finally { JDBCUtil.close(pst,conn,rs); } return list; }
}

資料庫連線

public class
JDBCUtil { private static DataSource ds; private static Properties p=new Properties(); static { try( //java6的新特性,try()中自動關閉 InputStream in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("db.properties") ) { p.load(in); /*Class.forName(p.getProperty("driverClassName"));*/ ds= DruidDataSourceFactory.createDataSource(p); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { /* try { return DriverManager.getConnection(p.getProperty("url"), p.getProperty("username"),p.getProperty("password")); } catch (SQLException throwables) { throwables.printStackTrace(); } return null;*/ return ds.getConnection(); }

我們需要在這裡面寫sql,連線資料庫,關閉資料庫連線,提交事務,

那麼假設我們有很多的表要寫,那這個工作量有多大?且sql和java程式碼混雜在一起,以後維護起來方便嗎?!

他可以解決我們什麼問題?

幫我們把sql語句抽取出來,讓程式碼便於維護,分離

連線資料庫,再也不用寫在java程式碼裡一個配置檔案搞定連線煩惱

環境準備

mybatis-xxx.jar

mysql-connector-java-xxx-bin.jar

2.mybatis: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>
  <environments default="dev_mysql">
    <environment id="dev_mysql">
        <!--Mybatis 內建事務管理器-->
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="admin"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
      <!--mapper檔案的路徑-->
    <mapper resource="xxx.xml"/>
  </mappers>
</configuration>

3.mapper對映檔案:XxxMapper.xml

mybatis中訪問的SQL語句都是在mapper配置檔案中的

<?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">
<!-- 配置對映
namespace : 名稱空間(通俗說法: 給當前對映檔案的唯一標識:起一個唯一的名字)    
 -->
<mapper namespace="cn.ss.mybatis.pojo.UserMapper">
    <!-- 新增操作
        id: 當前功能的唯一標識,和介面方法同名
        parameterType : 引數的型別
        useGeneratedKeys:是否返回資料庫生成的主鍵 true是/false否 
        keyProperty : 資料庫主鍵對應java的pojo物件的屬性
        keyColumn : 資料表的主鍵列明
     -->
    <insert id="insertUserInfo" parameterType="User" 
        useGeneratedKeys="true"
        keyProperty="id"
        keyColumn="id"
    ></mapper>

其實獲取連線物件還是需要用到連線池物件(為什麼使用連線池物件的原因是為了減少對資料庫資源浪費)

舉個栗子:

在沒有使用資料庫連線池之前,我們每次呼叫資料庫都要開一個數據庫連線

而資料庫的連線是有限的,當一個專案為了一些操作不斷的開啟資料庫連線

這樣最終會導致資料庫崩潰.

連線池就是起到,當你使用完資料庫連線後,呼叫關閉並不是放回資料庫,而是放入資料庫連線池等待下次呼叫

而mybatis的資料庫連線物件時SqlSessionFactory 中獲取SqlSession

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class
);
  Blog blog = mapper.selectBlog(101);
}

注意:這裡的(BlogMapper.class)指的是介面檔案的位元組碼檔案,要匹配到介面修改xml檔案的空間命名!!!!!

另外註解和通過SqlSession例項來直接執行SQL的我就不寫了(有想了解的百度吧)

ResultMap(正確書寫可以幫助你得到提交時的錯誤)

ResultMap 的設計思想是,簡單的語句不需要明確的結果對映,而複雜一點的語句只需要描述它們的關係就行了。

type 類的完全限定名, 或者一個類型別名 (內建的別名可以參考上面的表格).

association – 一個複雜型別的關聯;許多結果將包裝成這種型別

巢狀結果對映 – 關聯可以指定為一個 resultMap 元素,或者引用一個

<resultMap id="baseResultMap" type="Department">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--關聯屬性是集合型別 使用collection來配置
             select 傳送而外的sql
             column 而外sql引數之前sql那些列的值
             property 查詢結果封裝部門物件什麼屬性
        -->
        <collection select="cn.wolfcode.mapper.EmployeeMapper.queryById" column="id" property="employees"/>
    </resultMap>

命名引數@Param

經過JDBC的同學,應該已經嘗試過想在方法中傳遞多個引數,的操作吧?!

然後取不到值,其實當你傳遞多個引數給mapper時,這些引數就會被封裝到一個map中

而獲取的方法式

<select id="insertUserInfo" resultType="User" >
select * from user where password=#{param1} and username=#{param2}
</select>

通過預設命名獲取引數

而為了解決這種,不清晰的方式mybatis,提供了註解,讓你在傳遞多個引數前提前給個命名

void selectOne(@Param("username")String username,@Param("password")String password)

動態SQL

優勢:以前拼接的時候需要注意的空格、列表最後的逗號等,現在都可以不用手動處理了

  • if

    可選的查詢薪水功能

<select id="QueryByList" restult="employee">
SELECT id,name,salary 
FROM employee
where 
    <if test="minSalary !=null">
        salary &gt;=#{minSalary}
    </if>
    <if test="maxSalary !=null">
     and    salary &lt;=#{minSalary}
    </if>
</select>

  • choose (when, otherwise)

   在不想使用所有的條件,而只是想從多個條件選擇一個

<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

   前面案例運用if解決了可選查詢的問題,但是假設兩個條件多不成立,或前一個不成立呢?

<select id="QueryByList" restult="employee">
SELECT id,name,salary 
FROM employee
    <where>
    <if test="minSalary !=null">
        salary &gt;=#{minSalary}
    </if>
    <if test="maxSalary !=null">
     and    salary &lt;=#{minSalary}
    </if>
    </where>
</select>

  •   foreach
<!--    colletion 遍歷陣列或集合的key,或者屬性名
        open 遍歷開始拼接的字串
        index 遍歷索引
        item 遍歷元素
        separator 每遍歷一個元素拼接的字串
        close 遍歷拼接結束的字串

-->
    <delete id="batchDelete">
        delete from employee where id IN
        <foreach collection="ids" open="(" item="id" separator="," close=")">
            #{id}
        </foreach>

Mybatis的#和$的區別

相同點:

都可以獲取物件(Map物件或者JAVABean物件)資訊

不同點:

使用#傳遞的引數會先轉換為,無論傳遞是什麼型別資料都會帶一個單引號;$傳遞的引數,直接把值作為SQL語句的一部分

使用#支援把簡單型別引數作為值;$不支援簡單型別為值

使用#好比使用PrepareStatement,沒有sql注入的問題,比較安全;而$則反之

但這樣是不是$就沒用了呢?!

其實不然例如ORDER BY 或GROUP BY字句獲取引數值使用$,因為這樣會直接拼接在SQL上

(#加引號導致找不到列),因此若需要獲取引數才使用#

**(使用$可以攜帶常量)