国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

MyBatis學習筆記(二)——DAO的開發、配置文件、動態SQL

plus2047 / 2244人閱讀

摘要:建議不要在元素體內添加任何屬性值,只將屬性值定義在文件中。在文件中定義屬性名要有一定的特殊性防止覆蓋,如配置全局參數,在運行時可以調整一些運行參數。同樣需要遵守上面的規范。動態核心對語句進行靈活操作,通過表達式進行判斷,對進行靈活拼接組裝。

Hibernate與Mybatis的本質區別和應用場景

Hibernate:標準的ORM框架,不需要寫SQL語句,但是優化和修改SQL語句比較難。

應用于需求變化固定的中小型的項目,例如后臺管理系統、ERP、ORM、OA。

Mybatis:專注SQL本身,SQL的優化比較方便,是不完全的ORM。

主要適用于需求變化較多的項目,例如互聯網項目。

mybatis開發dao的方法 SqlSession的應用場合 SqlSessionFactoryBuilder

通過SqlSessionFactoryBuilder創建會話工廠SqlSessionFactory
將SqlSessionFactoryBuilder當成一個工具類使用即可,不需要使用單例管理SqlSessionFactoryBuilder。
在需要創建SqlSessionFactory時候,只需要new一次SqlSessionFactoryBuilder即可。

SqlSessionFactory

通過SqlSessionFactory創建SqlSession,使用單例模式管理sqlSessionFactory(工廠一旦創建,使用一個實例)。
mybatis和spring整合后,可以使用Ioc容器管理。

SqlSession

SqlSession是一個面向用戶(程序員)的接口。
SqlSession中提供了很多操作數據庫的方法:如:selectOne(返回單個對象)、selectList(返回單個或多個對象)。
SqlSession是線程不安全的,在SqlSesion實現類中除了有接口中的方法(操作數據庫的方法)還有數據域屬性。
SqlSession最佳應用場合在方法體內,定義成局部變量使用。

原始的DAO開發方法

程序員需要編寫DAO和DAO的實現類。需要向DAO實現類中注入SqlSessionFactory,在方法體內通過SqlSessionFactory來創建SqlSession。

定義DAO接口

public interface UserDAO {

    /**
     * 根據本id查詢用戶
     */
    User findUserById(int id) throws Exception;
    
    /**
     * 添加用戶
     */
    void insertUser(User user) throws Exception;
    
    /**
     * 根據id刪除用戶
     */
    void deleteUser(int id) throws Exception;
}

DAO實現類

/**
* @ClassName: UserDAOImpl 
* @Description: DAO實現類(注意:SqlSession是非線程安全的,故不能聲明為全局的)
 */
public class UserDAOImpl implements UserDAO {

    SqlSessionFactory sqlSessionFactory;
    /**
     * 向DAO實現類中注入SqlSessionFactory(此處通過構造方法注入)
     */
    public UserDAOImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    
    @Override
    public User findUserById(int id) throws Exception {
        
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", id);
        sqlSession.close();
        return user;
    }

    @Override
    public void insertUser(User user) throws Exception {
        
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
    }

    @Override
    public void deleteUser(int id) throws Exception {
        
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteUser", id);
        sqlSession.commit();
        sqlSession.close();
    }

}

新建一個源代碼目錄命名為test,在UserDAOImpl類中鼠標右鍵新建一個Junit Test Case,更換源代碼目錄為test并勾選我們需要測試的方法:

public class UserDAOImplTest {

    private SqlSessionFactory sqlSessionFactory;
    
    /**
     * 此方法在執行測試之前執行,得到一個SqlSessionFactory
     */
    @Before
    public void setUp() throws Exception {
        
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
    }

    @Test
    public void testFindUserById() throws Exception {
        // 創建UserDAO(在構造中注入SqlSessionFactory)
        UserDAO userDAO = new UserDAOImpl(sqlSessionFactory);
        User user = userDAO.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void testInsertUser() throws Exception {
        UserDAO userDAO = new UserDAOImpl(sqlSessionFactory);
        User user = new User();
        user.setSex("2");
        user.setUsername("孫悟空");
        user.setAddress("方寸靈臺山");
        user.setBirthday(new Date());
        userDAO.insertUser(user);
    }

    @Test
    public void testDeleteUser() throws Exception {
        UserDAO userDAO = new UserDAOImpl(sqlSessionFactory);
        userDAO.deleteUser(27);
    }

}
原始DAO開發中存在的問題

DAO的接口實現類中存在大量的模板方法,設想:可以將重復的代碼提取出來。

在SqlSession的方法時將Statement的id硬編碼在你DAO的實現類中。

調用sqlSession的相關方法傳入參數是泛型,即使傳入錯誤的參數,編譯時候也不會報錯

Mapper接口開發

程序員只需要編寫Mapper接口(相當于DAO接口)和Mapper.xml。Mapper接口的編寫需要遵守相關規范:

mapper.xml中的命名空間等于Mapper接口類的全路徑;

mapper.java中的方法名和mapper.xml中的statement的id一致;

mapper接口中方法的輸入參數類型和mapper.xml中的ParameterType一致;

mapper接口中的方法的返回值類型和mapper.xml中的ResultType一致。

遵循以上規范,mybatis就可以自動生成(反射機制)相關的mapper代理的實現類的對象。

UserMapper.xml




    










    
         SELECT  LAST_INSERT_ID();
    
    INSERT INTO user(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address});



    DELETE FROM user WHERE id = #{id}



    UPDATE user SET username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} WHERE id = #{id}

UserMapper.java

/**
* @Description: 用戶管理相關Mapper接口
 */
public interface UserMapper {

    /**
     * 根據本id查詢用戶
     */
    User findUserById(int id) throws Exception;
    
    /**
     * 根據用戶名模糊查詢用戶
     */
    List findUsersByName(String name) throws Exception;
    
    /**
     * 添加用戶
     */
    void insertUser(User user) throws Exception;
    
    /**
     * 根據id刪除用戶
     */
    void deleteUser(int id) throws Exception;
}

完成前面2步之后不要忘了在映射文件SqlMapConfig.xml中加載UserMapper.xml哦!



    
    

針對UserMapper接口編寫Junit單元測試:

public class UserMapperTest {

    private SqlSessionFactory sqlSessionFactory;
    
    @Before
    public void setUp() throws Exception {
        
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
    }

    @Test
    public void testFindUserById() throws Exception {
        
        // 得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 得到UserMapper對象(Mybatis自動生成Mapper代理對象)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 調用UserMapper的方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
        // 關閉SqlSession
        sqlSession.close();
    }

    @Test
    public void testFindUsersByName() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List users = userMapper.findUsersByName("明");
        System.out.println(users);
        sqlSession.close();
    }

    @Test
    public void testInsertUser() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setAddress("晴川");
        user.setUsername("百里屠蘇");
        user.setBirthday(new Date());
        user.setSex("1");
        userMapper.insertUser(user);
        sqlSession.commit();
        sqlSession.close();
        System.out.println(user.getId());
    }

    @Test
    public void testDeleteUser() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUser(28);
        sqlSession.commit();
        sqlSession.close();
    }

}

我們比較疑問的就是我們在UserMapper.xml的根據用戶名查找用戶的ResultType使用的是普通的POJO,但是我們自己的Mapper接口中返回值是List類型。這不就造成了類型不一致么?但是,實際上代理對象內部調用了selectOne()或者selectList(),代理對象內部會自動進行判斷是否是多帶帶的POJO選用合適的方法。

Mapper接口中方法的參數只有一個是否會影響系統的維護?DAO層的代碼是被業務層公用的,即使Mapper接口的參數只有一個我們也可以使用包裝的POJO來滿足系統需求。

注意:持久層中方法的參數中可以使用包裝類型,但是Service層中不建議使用包裝類型(不利于業務層的拓展維護)。

SqlMapConfig.xml文件 屬性配置

該配置文件是mybatis的全局配置文件,配置內容如下:

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

將數據庫連接參數多帶帶配置在db.properties中,只需要在SqlMapConfig.xml中加載db.properties的屬性值。
在SqlMapConfig.xml中就不需要對數據庫連接參數硬編碼。

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

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=mysqladmin

在SqlMapConfig中加載屬性文件:





    
    
        
    
    
    
        
            
            
                
            
             
             
                
                
                
                
            
        
    

properties特性:

注意: MyBatis 將按照下面的順序來加載屬性:

在 properties 元素體內定義的屬性首先被讀取。

然后會讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。

最后讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性。

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

 settings

settings配置全局參數,mybatis在運行時可以調整一些運行參數。例如:開啟二級緩存、開啟延遲加載。參數詳見:Mybatis settings詳解

typeAliases

在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入參數的類型、需要resultType指定輸出結果的映射類型。

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

mybatis內置的別名

自定義別名

在SqlMapConfig.xml中配置別名:



    
    

在mapperr.xml中使用別名替代ResultType:


以上的方法是定義簡單的單個別名,我們也可以使用批量別名定義:



    
    

在mapper.xml中我們可以使用以上的別名,此時是大小寫不敏感的:


其中批量設置別名比較常用(只需要配置po所在的類路徑即可)。

TypeHandlers

類型處理器,mybatis通過typeHandlers完成JDBC類型和java類型的轉化。一般來說自帶的類型處理器已經夠用了,不需要多帶帶定義。

mapper

映射配置。

通過resource一次加載一個映射文件:

通過mapper接口加載單個映射文件,需要遵循相關的規范:將mapper.xml和mapper接口的名稱保持一致且在一個目錄中(前提是使用mapper代理的方式進行開發)。


批量加載mapper。同樣需要遵守上面的規范。

輸入映射

通過parameterType來指定輸入參數的類型,可以是簡單類型、hashmap、pojo。

傳遞POJO的包裝對象

需求:完成用戶信息的綜合查詢,需要傳入查詢條件很復雜(可能包括用戶信息、其它信息,比如商品、訂單的)

針對上邊需求,建議使用自定義的包裝類型的pojo。在包裝類型的pojo中將復雜的查詢條件包裝進去。

新建一個UserCustomer類(該類繼承User,實現對Us而的拓展)

/**
* @ClassName: UserCustom 
* @Description: 用戶拓展類
 */
public class UserCustom extends User {

}

新建一個UserQueryVO(在該類內部以組合的方式包裝UserCustomer類)

/**
* @ClassName: UserQueryVO 
* @Description: 視圖層面javabean(用來包裝查詢條件)
 */
public class UserQueryVO {

    // 包裝所需要的查詢條件(可以通過組合的方式包裝其他的查詢條件,例如:商品、訂單)
    private UserCustom userCustom;

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }
    
}

mapper.xml。在UserMapper.xml中定義用戶信息的綜合(復雜的關聯查詢)查詢。


mapper.java。在UserMapper接口中增加一個方法。

/**
 * 用戶信息的綜合查詢
 */
List findUserList(UserQueryVO userQueryVO) throws Exception;

測試類

@Test
public void testfindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 創建包裝對象,傳入查詢條件
    UserQueryVO userQueryVO = new UserQueryVO();
    UserCustom userCustom = new UserCustom();
    userCustom.setSex("1");
    userCustom.setUsername("明");
    userQueryVO.setUserCustom(userCustom);
    List users = userMapper.findUserList(userQueryVO);
    System.out.println(users);
}
輸出映射 ResultType

使用ResultType進行輸出映射只有當查詢輸出列名和POJO中的字段名一致時,該列才可以映射成功;如果查詢出來的列名和屬性名全部不一致(例如使用了SQL的別名);一旦有一個查詢的輸出列名和POJO的屬性名一致就會映射成對象。

需求:用戶信息的綜合查詢列表總數,并結合上邊的綜合查詢列表實現分頁功能。

mapper.xml


mapper.java

/**
 * 用戶信息的綜合查詢總數
 */
int findUserCount(UserQueryVO userQueryVO) throws Exception;

測試類:

@Test
public void testFindUserCount() throws Exception{
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 創建包裝對象,傳入查詢條件
    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);
}

小結:

查詢出來的結果集只有一行且一列,可以使用簡單類型進行輸出映射。

輸出POJO對象和POJO列表。

不管是輸出的pojo單個對象還是一個列表(list中包括pojo),在mapper.xml中resultType指定的類型是一樣的。
在mapper.java指定的方法返回值類型不一樣

生成的動態代理對象中是根據mapper方法的返回值類型確定是調用selectOne(返回單個對象調用)還是selectList (返回集合對象調用 ).

ResultMap

可以使用ResultMap來完成高級的輸出結果映射。如果數據庫輸出的列名和POJO的屬性名不一致,就可以通過定義ResultMap對列名和屬性名進行我們自己的映射。

范例:使用ResultMap改寫以下的SQL,完成輸出結果的映射;

SELECT id _id,username _username FROM user WHERE id = #{value}

UserMapper.xml



    
    
    
    


UserMapper.java

/**
 * 根據id查詢用戶(通過ResultMap手工完成映射)
 */
User findUserByIdResultMap(int id) throws Exception;

測試類:

@Test
public void testFindUserByIdResultMap() throws Exception{
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findUserByIdResultMap(1);
    System.out.println(user);
    sqlSession.close();
}

小結:

使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。

如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。

動態SQL

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

if判斷

需求:用戶信息綜合查詢列表和用戶信息查詢列表總數這兩個statement的定義使用動態sql。對查詢條件進行判斷,如果輸入參數不為空才進行查詢條件拼接。

if判斷類似于JSTL.

mapper.xml



maper.java

/**
 * 用戶信息的綜合查詢
 */
List findUserList(UserQueryVO userQueryVO) throws Exception;

/**
 * 用戶信息的綜合查詢總數
 */
int findUserCount(UserQueryVO userQueryVO) throws Exception;

測試類

@Test
public void testfindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 取消部分查詢條件
    UserQueryVO userQueryVO = new UserQueryVO();
    UserCustom userCustom = new UserCustom();
//        userCustom.setSex("1");
    userCustom.setUsername("明");
    userQueryVO.setUserCustom(userCustom);
    List users = userMapper.findUserList(userQueryVO);
    System.out.println(users);
}

@Test
public void testFindUserCount() throws Exception{
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 取消部分查詢條件
    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片段

以上的代碼中mapper.xml中的SQL語句有一些重復,我們可以將上面的動態SQL中共有的部分抽取出來形成自己的sql片段,在其他的Statement中就可以使用此SQL片段。

定義并使用SQL片段



    
        
            AND user.sex = #{userCustom.sex}
        
        
            AND user.username LIKE "%${userCustom.username}%"
        
    

for-each

向sql傳遞數組或List,mybatis使用foreach解析。

例如:在用戶查詢列表和查詢總數的statement中增加多個id輸入查詢。
兩種方法:

SELECT * FROM USER WHERE id=1 OR id=10 OR id=16

SELECT * FROM USER WHERE id IN(1,10,16)

在輸入參數類型中添加List ids傳入多個id(并添加getter和setter)

修改mapper.xml中的SQL片段



    
        
            AND user.sex = #{userCustom.sex}
        
        
            AND user.username LIKE "%${userCustom.username}%"
        
    
    
        
         
        
            
            id=#{user_id}
        
    

測試類:

@Test
public void testfindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    UserQueryVO userQueryVO = new UserQueryVO();
    UserCustom userCustom = new UserCustom();
    userCustom.setUsername("明");
    
    // 傳入多個id
    List ids = Arrays.asList(1,16,22,25);
    userQueryVO.setId(ids);
    userQueryVO.setUserCustom(userCustom);
    List users = userMapper.findUserList(userQueryVO);
    System.out.println(users);
}


        每個遍歷需要拼接的串
        #{user_id}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64550.html

相關文章

  • 通過項目逐步深入了解Mybatis<>

    摘要:的實例不能共享使用,它也是線程不安全的。因此最佳的范圍是請求或方法范圍定義局部變量使用。在中就不需要直接對數據庫的連接參數進行硬編碼了。 轉載請務必注明出處,原創不易! 相關文章:通過項目逐步深入了解Mybatis 本項目全部代碼地址:Github-Mybatis Mybatis 解決 jdbc 編程的問題 1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用...

    BigTomato 評論0 收藏0
  • JAVA學習筆記036-第一個簡單Mybatis程序(代碼經驗證)

    摘要:目標創建一個簡單的框架的程序,實現對數據庫的讀取操作。的核心配置文件核心配置文件,配置數據庫連接信息事物等每一個都需要在核心配置文件中注冊工具類獲取第一步獲取對象既然有了,顧名思義,我們可以從中獲得的實例。 ...

    itvincent 評論0 收藏0
  • Mybatis常見面試題

    摘要:執行沒有,批處理不支持,將所有都添加到批處理中,等待統一執行,它緩存了多個對象,每個對象都是完畢后,等待逐一執行批處理。 Mybatis常見面試題 #{}和${}的區別是什么? #{}和${}的區別是什么? 在Mybatis中,有兩種占位符 #{}解析傳遞進來的參數數據 ${}對傳遞進來的參數原樣拼接在SQL中 #{}是預編譯處理,${}是字符串替換。 使用#{}可以有效的防止...

    liuchengxu 評論0 收藏0
  • Java面試前需要了解東西

    摘要:我在面試前針對基礎也花了不少的時間,期間也將自己寫過的博文粗略地刷了一遍,同時也在網上找了不少比較好的資料部分是沒看完的。看面試題也是校驗自己是否真正理解了這個知識點,也很有可能會有新的收獲。 一、前言 只有光頭才能變強 回顧前面: 廣州三本找Java實習經歷 上一篇寫了自己面試的經歷和一些在面試的時候遇到的題目(筆試題和面試題)。 我在面試前針對Java基礎也花了不少的時間,期間也將...

    renweihub 評論0 收藏0

發表評論

0條評論

plus2047

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<