Mybatis----(1)

主要內容
1、對原生態(tài)jdbc程序(單獨使用jdbc開發(fā))問題總結
2、mybatis框架原理
3、mybatis入門程序
4、mybatis開發(fā)dao兩種方法
5、mybatis配置文件SqlMapConfig.xml
6、mybatis核心
7、mybatis的動態(tài)sql

1、原生態(tài)jdbc程序中問題總結

下面的代碼,有很多問題,總結如下:

public class JdbcTest {
    
    public static void main(String[] args) {
        
        //數(shù)據(jù)庫連接
        Connection connection = null;
        //預編譯的Statement,使用預編譯的Statement提高數(shù)據(jù)庫性能
        PreparedStatement preparedStatement = null;
        //結果 集
        ResultSet resultSet = null;
        
        try {
            //加載數(shù)據(jù)庫驅動
            Class.forName("com.mysql.jdbc.Driver");
            
            //通過驅動管理類獲取數(shù)據(jù)庫鏈接
            connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql");
            //定義sql語句 ?表示占位符
            String sql = "select * from user where username = ?";
            //獲取預處理statement
            preparedStatement = connection.prepareStatement(sql);
            //設置參數(shù),第一個參數(shù)為sql語句中參數(shù)的序號(從1開始),第二個參數(shù)為設置的參數(shù)值
            preparedStatement.setString(1, "王五");
            //向數(shù)據(jù)庫發(fā)出sql執(zhí)行查詢,查詢出結果集
            resultSet =  preparedStatement.executeQuery();
            //遍歷查詢結果集
            while(resultSet.next()){
                System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //釋放資源
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }


    }
}

1、數(shù)據(jù)庫連接,使用時就創(chuàng)建,不使用立即釋放,對數(shù)據(jù)庫進行頻繁連接開啟和關閉,造成數(shù)據(jù)庫資源浪費,影響 數(shù)據(jù)庫性能。
設想:使用數(shù)據(jù)庫連接池管理數(shù)據(jù)庫連接。

2、將sql語句硬編碼到java代碼中,如果sql 語句修改,需要重新編譯java代碼,不利于系統(tǒng)維護。
設想:將sql語句配置在xml配置文件中,即使sql變化,不需要對java代碼進行重新編譯。

3、向preparedStatement中設置參數(shù),對占位符號位置和設置參數(shù)值,硬編碼在java代碼中,不利于系統(tǒng)維護。
設想:將sql語句及占位符號和參數(shù)全部配置在xml中。

4、從resutSet中遍歷結果集數(shù)據(jù)時,存在硬編碼,將獲取表的字段進行硬編碼,,不利于系統(tǒng)維護。
設想:將查詢的結果集,自動映射成java對象。

2、mybatis框架

2-1 mybatis是什么?

mybatis是一個持久層的框架,是apache下的頂級項目。

mybatis讓程序將主要精力放在sql上,通過mybatis提供的映射方式,自由靈活生成(半自動化,大部分需要程序員編寫sql)滿足需要sql語句。

mybatis可以將向 preparedStatement中的輸入?yún)?shù)自動進行輸入映射,將查詢結果集靈活映射成java對象。(輸出映射)

2-2 mybatis框架

image.png

2-3 mybatis使用步驟(基礎方式1)

image.png

1 讀取SqlMapConfig.xml文件,其中配置了Mybatis的基本信息

private SqlSessionFactory sqlSessionFactory;

    // 此方法是在執(zhí)行testFindUserById之前執(zhí)行
    @Before
    public void setUp() throws Exception {
        // 創(chuàng)建sqlSessionFactory

        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創(chuàng)建會話工廠,傳入mybatis的配置文件信息
        sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);
    }

2 配置mybatis的運行環(huán)境,數(shù)據(jù)源、事務等。

<configuration>
    <!-- 加載屬性文件 -->
    <properties resource="db.properties">
        <!--properties中還可以配置一些屬性名和屬性值  -->
        <!-- <property name="jdbc.driver" value=""/> -->
    </properties>


    <!-- 和spring整合后 environments配置將廢除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事務管理,事務控制由mybatis-->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>


    <mappers>
        <mapper resource="sqlmap/User.xml"/>
    </mappers>

</configuration>

3 新建xml的sql對象

<mapper namespace="test">

    <!--如果輸入 參數(shù)是簡單類型,#{}中的參數(shù)名可以任意,可以value或其它名稱-->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        select * from user where id = #{value}
    </select>

    <!-- ${value}:接收輸入 參數(shù)的內容,如果傳入類型是簡單類型,${}中只能使用value
     返回值是list還是單個值,通過接口的返回值確定
     -->
    <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
        SELECT * FROM USER WHERE username LIKE '%${value}%'
    </select>


    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
   </insert>


    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>


    <update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
        update user set sex=#{sex}
        where id=#{id}
    </update>

</mapper>

4 定義接口和實現(xiàn)類

接口

public interface UserDao {

    //根據(jù)id查詢用戶信息
    public User findUserById(int id) throws Exception;

    //根據(jù)用戶名列查詢用戶列表
    public List<User> findUserByName(String name) throws Exception;

    //添加用戶信息
    public void insertUser(User user) throws Exception;

    //刪除用戶信息
    public void deleteUser(int id) throws Exception;


    public void updateUser(User user) throws Exception;
}

實現(xiàn)類

// 需要向dao實現(xiàn)類中注入SqlSessionFactory
    // 這里通過構造方法注入
    private SqlSessionFactory sqlSessionFactory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }


    public User findUserById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        User user = sqlSession.selectOne("test.findUserById", id);

        // 釋放資源
        sqlSession.close();

        return user;
    }

    public List<User> findUserByName(String name) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        List<User> list = sqlSession.selectList("test.findUserByName", name);

        // 釋放資源
        sqlSession.close();

        return list;
    }

    public void insertUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //執(zhí)行插入操作
        sqlSession.insert("test.insertUser", user);

        // 提交事務
        sqlSession.commit();

        // 釋放資源
        sqlSession.close();
    }

    public void deleteUser(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //執(zhí)行插入操作
        sqlSession.delete("test.deleteUser", id);

        // 提交事務
        sqlSession.commit();

        // 釋放資源
        sqlSession.close();
    }

    public void updateUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //執(zhí)行插入操作
        sqlSession.update("test.updateUser", user);

        // 提交事務
        sqlSession.commit();

        // 釋放資源
        sqlSession.close();
    }

3 mybatis使用方式(2)---- mapper代理

可以發(fā)現(xiàn)上述的接口實現(xiàn)類中存在大量的重復代碼

所以Mybatis還提供直接通過xml來執(zhí)行的sql語句的方式

1 測試類代碼

 @Test
    public void findUserId() throws Exception{
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //創(chuàng)建UserMapper對象,mybatis自動生成mapper代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //調用userMapper的方法
        User user = userMapper.findUserId(1);
        
        System.out.println(user);
    }
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
    <select id="findUserId" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        select * from user where id=#{value}
    </select>
</mapper>

上面的測試類代碼是可以直接通過匹配xml中的id調用xml的sql語句執(zhí)行查詢的
User user = userMapper.findUserId(1);
,簡化了實現(xiàn)類的書寫。

開發(fā)規(guī)范:

1、在mapper.xml中namespace等于mapper接口地址
2、mapper.java接口中的方法名和mapper.xml中statement的id一致
3、mapper.java接口中的方法輸入?yún)?shù)類型和mapper.xml中statement的parameterType指定的類型一致。
4、mapper.java接口中的方法返回值類型和mapper.xml中statement的resultType指定的類型一致。

總結:
以上開發(fā)規(guī)范主要是對下邊的代碼進行統(tǒng)一生成:

User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);

4 SqlMapConfig.xml的配置

mybatis的全局配置文件SqlMapConfig.xml,配置內容如下:

properties(屬性)
settings(全局配置參數(shù))
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環(huán)境集合屬性對象)
environment(環(huán)境子屬性對象)
transactionManager(事務管理)
dataSource(數(shù)據(jù)源)
mappers(映射器)

4-1 properties屬性

可將數(shù)據(jù)庫連接參數(shù)單獨配置在db.properties中,只需要在SqlMapConfig.xml中加載db.properties的屬性值。
在SqlMapConfig.xml中就不需要對數(shù)據(jù)庫連接參數(shù)硬編碼。

將數(shù)據(jù)庫連接參數(shù)只配置在db.properties中,原因:方便對參數(shù)進行統(tǒng)一管理,其它xml可以引用該db.properties。

    <!-- 加載屬性文件 -->
    <properties resource="db.properties">
        <!--properties中還可以配置一些屬性名和屬性值  -->
        <!-- <property name="jdbc.driver" value=""/> -->
    </properties>

建議:
不要在properties元素體內添加任何屬性值,只將屬性值定義在properties文件中。
在properties文件中定義屬性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

4-2 settings全局參數(shù)配置

mybatis框架在運行時可以調整一些運行參數(shù)。
比如:開啟二級緩存、開啟延遲加載。。

全局參數(shù)將會影響mybatis的運行行為。

4-3 typeAliases(別名)重點

在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入?yún)?shù)的類型、需要resultType指定輸出結果的映射類型。

如果在指定類型時輸入類型全路徑,不方便進行開發(fā),可以針對parameterType或resultType指定的類型定義一些別名,在mapper.xml中通過別名定義,方便開發(fā)。

<!-- 別名定義 -->
    <typeAliases>
        
        <!-- 針對單個別名定義
        type:類型的路徑
        alias:別名
         -->
        <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> 
        <!-- 批量別名定義 
        指定包名,mybatis自動掃描包中的po類,自動定義別名,別名就是類名(首字母大寫或小寫都可以)
        -->
        <package name="cn.itcast.mybatis.po"/>
        
    </typeAliases>

4-4 mappers(映射配置)

1 通過resource加載單個映射文件

2 通過mapper接口加載單個mapper

3 批量加載mapper(推薦使用)

<mappers>
        <!-- <mapper resource="sqlmap/User.xml"/> -->
        
        <!--通過resource方法一次加載一個映射文件 -->
        <!-- <mapper resource="mapper/UserMapper.xml"/> -->
        
        <!-- 通過mapper接口加載單個 映射文件
        遵循一些規(guī)范:需要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄 中
        上邊規(guī)范的前提是:使用的是mapper代理方法
         -->
        <!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> -->
        
        <!-- 批量加載mapper
        指定mapper接口的包名,mybatis自動掃描包下邊所有mapper接口進行加載
        遵循一些規(guī)范:需要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄 中
        上邊規(guī)范的前提是:使用的是mapper代理方法
         -->
        <package name="cn.itcast.mybatis.mapper"/>
    </mappers>

5 輸入映射(parameterType)和輸出映射(resultType)

輸入映射:

通過parameterType指定輸入?yún)?shù)的類型,類型可以是簡單類型、hashmap、pojo的包裝類型。

注意:
1、使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
2、如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創(chuàng)建pojo對象。
3、只要查詢出來的列名和pojo中的屬性有一個一致,就會創(chuàng)建pojo對象,不一致的屬性的值為null。

輸出映射:

使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創(chuàng)建pojo對象。
只要查詢出來的列名和pojo中的屬性有一個一致,就會創(chuàng)建pojo對象,不一致的屬性的值為null。

    <!-- 用戶信息綜合查詢
    #{userCustom.sex}:取出pojo包裝對象中性別值
    ${userCustom.username}:取出pojo包裝對象中用戶名稱
     -->
    <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" 
            resultType="cn.itcast.mybatis.po.UserCustom">
            SELECT * FROM USER
    </select>
    @Test
    public void testFindUserList() throws Exception {
        
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        //創(chuàng)建UserMapper對象,mybatis自動生成mapper代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        
        //創(chuàng)建包裝對象,設置查詢條件
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustom userCustom = new UserCustom();
        //由于這里使用動態(tài)sql,如果不設置某個值,條件不會拼接在sql中
//      userCustom.setSex("1");
        userCustom.setUsername("小明");
        //傳入多個id
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(10);
        ids.add(16);
        //將ids通過userQueryVo傳入statement中
        userQueryVo.setIds(ids);
        userQueryVo.setUserCustom(userCustom);
        //調用userMapper的方法
        
        List<UserCustom> list = userMapper.findUserList(userQueryVo);
        
        System.out.println(list);       
    }

6 動態(tài)sql

mybatis核心。對sql語句進行靈活操作,通過表達式進行判斷,對sql進行靈活拼接、組裝。

nobibi,show you my code

 @Test
    public void findUserCount() throws Exception  {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //創(chuàng)建UserMapper對象,mybatis自動生成mapper代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //創(chuàng)建包裝對象,設置查詢條件
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustom userCustom = new UserCustom();
        userCustom.setSex("1");
        userCustom.setUsername("張三豐");
        userQueryVo.setUserCustom(userCustom);

        int count = userMapper.findUserCount(userQueryVo);

        System.out.println(count);
    }
<!-- 定義sql片段
    id:sql片段的唯 一標識
    
    經驗:是基于單表來定義sql片段,這樣話這個sql片段可重用性才高
    在sql片段中不要包括 where
     -->
    <sql id="query_user_where">
        <if test="userCustom!=null">
          <if test="userCustom.sex!=null and userCustom.sex!=''">
              and user.sex = #{userCustom.sex}
          </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
                and user.username LIKE '%${userCustom.username}%'
            </if>
        </if>
    </sql>
<!-- 用戶信息綜合查詢總數(shù)
    parameterType:指定輸入類型和findUserList一樣
    resultType:輸出結果類型
     -->
    <select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="int">
       SELECT count(*) FROM USER 
       
      <!-- 
    where可以自動去掉條件中的第一個and
     -->
    <where>
        <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前邊加namespace -->
        <include refid="query_user_where"></include>
        <!-- 在這里還要引用其它的sql片段  -->
    </where>       
    </select>

感覺這個功能很NP,要善用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 之前在面試工作的時候,我當時用的是hibernate,但是現(xiàn)在互聯(lián)網(wǎng)項目并發(fā)量大,一般都會選擇使用Mybatis,...
    唐偉耀閱讀 596評論 1 0
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,241評論 0 4
  • 偶爾會發(fā)現(xiàn),之前照過的照片會很像你印象中的一幅畫,做過的事也會有似曾相識的感覺。
    倚軒聽雨閱讀 282評論 0 0
  • 綠大衣配白毛衣 綠毛衣配黃大衣 同一條褲子同一雙皮靴 一天一天,日子就過去了 就不冷了,又幸福又簡單 池塘邊的柳樹...
    鶑鵅閱讀 195評論 0 1
  • 愛豆美雪大神寫給以前戀人拓郎"像遺書一般的歌曲",每每聽罷,感慨萬千。再見還是初戀般嬌羞的感覺。 聽說紐約正是大雪...
    TNANNAN閱讀 806評論 0 0

友情鏈接更多精彩內容