天天看點

基于代理Dao實作CRUD操作根據ID查詢儲存操作使用者更新使用者删除使用者模糊查詢MyBatis和JDBC的差別

使用要求:

1、持久層接口和持久層接口的映射配置必須在相同的包下

2、持久層映射配置中mapper标簽的namespace屬性取值必須是持久層接口的全限定類名

3、sql語句的配置标簽,,,的id屬性必須和持久層接口的方法名相同

根據ID查詢

1、 在持久層接口中添加findById方法

/**
     * 根據id查詢使用者資訊
     * @param userId
     * @return
     */
    User findById(Integer userId);
           

2、在使用者的映射配置檔案中配置

<!-- 根據id查詢使用者 -->
    <select id="findById" parameterType="INT" resultType="com.itheima.domain.User">
        select * from user where id = #{uid}
    </select>

           

resultType屬性:用于指定結果集的類型

parameterType屬性:用于指定傳入參數的類型

sql語句中使用#{}:代表占位符,相當于jdbc中的?,用于執行語句時替換實際的資料,具體的資料由#{}裡面的内容決定,由于資料類型是基本類型,#{}内可以随意寫。

3、在測試類添加測試

public class MybatisTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;
  

    @Before//用于在測試方法執行之前執行
    public void init()throws Exception{
        //1.讀取配置檔案,生成位元組輸入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2. 建立建構者對象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.建立SqlSessionFactory對象
        factory = builder.build(in);
        //4.建立SqlSession對象
        session = factory.openSession();
        //5.建立Dao的代理對象
        userDao = session.getMapper(IUserDao.class);
    }

    @After//用于在測試方法執行之後執行
    public void destroy()throws Exception{
         session.commit();
        //7.釋放資源
        session.close();
        in.close();
    }'  
    @Test
    public void testFindOne(){
        //5.執行查詢一個方法
        User  user = userDao.findById(41);
        System.out.println(user);
    }

           

儲存操作

1、在持久層接口中添加新增方法

/**
     * 儲存使用者
     * @param user
     */
 void saveUser(User user);
           

2、在使用者的映射配置檔案中配置

<!-- 儲存使用者 -->
    <insert id="saveUser" parameterType="com.itheima.domain.User">
             insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday});
    </insert>
           

parameterType屬性:代表參數的類型,因為我們要傳入一個類的對象,是以類型就寫類的全名稱、

#{}内容:由于儲存方法的參數是一個User對象,此處要寫User對象中的屬性名稱,使用ognl表達式

ognl(object graphic navigation language)表達式:對象圖導航語言。按照一定的文法格式來擷取資料,#{對象.對象}

#{user.username}先找到user對象,然後在user對象中找到username屬性,并調用getUsername()方法把值取出來。但是我們在parameterType屬性上制定了實體類名稱,是以可以省略user直接寫username.

3、添加測試類中的測試方法

/**
     * 測試儲存操作
     */
    @Test
    public void testSave(){
        User user = new User();
        user.setUserName("modify User property");
        user.setUserAddress("北京市順義區");
        user.setUserSex("男");
        user.setUserBirthday(new Date());
        System.out.println("儲存操作之前:"+user);
        //5.執行儲存方法
        userDao.saveUser(user);

        System.out.println("儲存操作之後:"+user);
    }
           

此時mysql資料庫中沒有任何添加紀錄,因為在實作增删改時一定要去控制事務的送出,在myBatis中使用sqlSession.commit()

@After//用于在測試方法執行之後執行
    public void destroy()throws Exception{
        //送出事務
        sqlSession.commit();
        //6.釋放資源
        sqlSession.close();
        in.close();
    }
           

4、新增使用者Id的傳回值

新增使用者後,同時還要傳回目前新增使用者的id值,因為id是由資料庫的自動增長來實作的,是以就相當于我們要在新增後将自動增長的auto_increment的值傳回。

<!-- 儲存使用者 -->
    <insert id="saveUser" parameterType="com.itheima.domain.User">
        <!-- 配置插入操作後,擷取插入資料的id -->
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
    </insert>
           

使用者更新

1、在持久層接口中添加更新方法

/**
     * 更新使用者
     * @param user
     */
   void updateUser(User user);

           

2、在使用者的映射配置檔案中配置

<!-- 更新使用者 -->
    <update id="updateUser" parameterType="com.itheima.domain.User">
        update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}
    </update>
           

3、加入更新的測試方法

/**
     * 測試更新操作
     */
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(50);
        user.setUsername("userdaoimpl update user");
        user.setAddress("北京市順義區");
        user.setSex("女");
        user.setBirthday(new Date());

        //執行更新方法
        userDao.updateUser(user);
    }

           

使用者删除

1、在持久層接口中添加删除方法

/**
     * 根據Id删除使用者
     * @param userId
     */
    void deleteUser(Integer userId);
           

2、在使用者的映射配置檔案中配置

<!-- 删除使用者-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>
           

3、加入删除的測試方法

/**
     * 測試删除操作
     */
    @Test
    public void testDelete(){
        //5.執行删除方法
        userDao.deleteUser(54);
    }
           

使用者模糊查詢

在持久層接口中添加模糊查詢方法

/**
     * 根據名稱模糊查詢使用者資訊
     * @param username
     * @return
     */
    List<User> findByName(String username);
           

在使用者的映射配置檔案中配置

<!-- 根據名稱模糊查詢 -->
    <select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
          select * from user where username like #{name}
   </select>

           

加入模糊查詢的測試方法

/**
     * 測試模糊查詢操作
     */
    @Test
    public void testFindByName(){
        //5.執行查詢一個方法
        List<User> users = userDao.findByName("%王%");
        for(User user : users){
            System.out.println(user);
        }
    }

           

配置檔案中沒有加入%來作為模糊查詢的條件,是以在傳入字元串實參時,就需要給定模糊查詢的表示%,配置檔案中的#{username}也隻是一個占位符,是以sql語句顯示為?

模糊查詢的另一種配置方式

1、修改sql語句的配置

<!-- 根據名稱模糊查詢 -->
    <select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
          select * from user where username like **'%${value}%'**
   </select>

           
将原來的#{}占位符,改為

${value}

。如果使用模糊查詢的寫法,

${value}

的寫法時固定的

2、測試

/**
     * 測試模糊查詢操作
     */
    @Test
    public void testFindByName(){
        //5.執行查詢一個方法
        List<User> users = userDao.findByName("王");
        for(User user : users){
            System.out.println(user);
        }
    }

           
這種查詢方式不需要加入模糊查詢的比對符$

#{}與${}的差別

#{}表示一個占位符号

  • 通過#{}可以實作 preparedStatement 向占位符中設定值,自動進行 java 類型和 jdbc 類型轉換, #{}可以有效防止 sql 注入。 #{}可以接收簡單類型值或 pojo 屬性值。 如果 parameterType 傳輸單個簡單類 型值,#{}括号中可以是 value 或其它名稱。

${}表示拼接sql串

  • 通過${}可以将 parameterType 傳入的内容拼接在 sql中且不進行 jdbc 類型轉換, 可 以 接 收 簡 單 類 型 值 或 p o j o 屬 性 值 , 如 果 p a r a m e t e r T y p e 傳 輸 單 個 簡 單 類 型 值 , {}可以接收簡 單類型值或 pojo 屬性值,如果 parameterType 傳輸單個簡單類型值, 可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,{}括号中隻能是 value。

MyBatis和JDBC的差別

  • 1.資料庫連結建立、釋放頻繁造成系統資源浪費進而影響系統性能,如果使用資料庫連結池可解決此問題。 解決: 在 SqlMapConfig.xml 中配置資料連結池,使用連接配接池管理資料庫連結。
  • 2.Sql 語句寫在代碼中造成代碼不易維護,實際應用 sql 變化的可能較大,sql 變動需要改變 java 代碼。 解決: 将 Sql 語句配置在 XXXXmapper.xml 檔案中與 java 代碼分離。
  • 3.向sql語句傳參數麻煩,因為sql語句的where 條件不一定,可能多也可能少,占位符需要和參數對應。 解決: Mybatis自動将 java 對象映射至 sql 語句,通過 statement 中的 parameterType 定義輸入參數的 類型。
  • 4.對結果集解析麻煩,sql 變化導緻解析代碼變化,且解析前需要周遊,如果能将資料庫記錄封裝成 pojo 對 象解析比較友善。 解決: Mybatis自動将 sql執行結果映射至 java 對象,通過statement中的resultType 定義輸出結果的 類型。