1. 程式人生 > >MyBatis(2)增刪改查

MyBatis(2)增刪改查

簡單的 就是 cst 學習 解析 百分號 鍵值 入門 system

本次全部學習內容:MyBatisLearning

查: 根據id查詢用戶信息,得到一個用戶信息 在User.xml文件中添加代碼:
 <mapper namespace="test">
    <!-- 配置很多的sql語句 -->
     
     <!-- 查詢標簽 -->
     <!-- id用於唯一標識這個sql查詢 -->
     <!-- #{} 標識占位符 -->
     <!-- parameterType:指定輸入參數的類型: -->
     <!-- #{id}:接受輸入的參數,id表示輸入的參數,參數名就是id,如果輸入參數是簡單的類型,#{}中的參數可以是任意字符 -->
     <!-- resultType:輸出結果的類型 所映射的java 類型對象,單挑記錄所映射成的java對象-->
<select id="findUserByID" parameterType="int" resultType="com.MrChengs.po.User"> select * from user where id=#{id} </select> </mapper>
在測試代碼中test.java:
//根據id查詢用戶信息,得到一個用戶信息
     @Test
     public void findUserById() throws IOException{
           
           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);
           
           //創建會話工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     
           //通過工程得到Session
           SqlSession session = sessionFactory.openSession();
           
           //通過SqlSession操作數據庫
           //session.selectOne(arg0, arg1)
           //第一個參數:映射文件statement的id,等於 namespace.statement
           //第二個參數:指映射文件的中的parameType的類型參數
           
           User user = session.selectOne("test.findUserByID", 10
); System.out.println(user); //關閉資源 session.close(); }
這裏的代碼使用try{}finally{} 和jdbc類似,暫時沒有使用! 控制臺的結果:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 733957003.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b]
DEBUG [main] - ==>  Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 10(Integer)
DEBUG [main] - <==      Total: 1
User [id=10, username=張三, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=
北京市] DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b] DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b] DEBUG [main] - Returned connection 733957003 to pool.

根據用戶名稱來模糊查詢用戶信息: 在User,xml文件中添加代碼:
     <!-- 模糊查詢 -->
     <!-- resultType:指定單挑記錄所映射的類型 -->
     <select id="findByName" parameterType="java.lang.String" resultType="com.MrChengs.po.User" >
           select * from user where username Like #{username}
     </select>
其余不變去測試代碼中 在測試代碼中test.java:
//根據用戶名稱來模糊查詢用戶
     @Test
public void findUserByName() throws IOException{
           
           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);
           
           //創建會話工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     
           //通過工程得到Session
           SqlSession session = sessionFactory.openSession();
           
           //通過SqlSession操作數據庫
           //selectList(String arg0, Object arg1)
           //list中的user和映射文件中的resultType所指類型一直
           //百分號不能忘記添加
           List<User> users = session.selectList("test.findByName", "%小明%");
           for(User user : users){
                System.out.println(user);
           }
           //關閉資源
           session.close();
     }
     

註意紅色標記的部分。

思考:我們可不可以不在測試類中添加百分號? 我們這本此程序代碼的基礎上進行改進: 在User,xml文件中:
<!-- 模糊查詢 -->
     <!-- resultType:指定單挑記錄所映射的類型 -->
     
     <!-- ${} :表示拼接sql串,將接收的參數的內容不加任何修飾的拼接在sql中 -->
     <!-- 使用 ${ } 拼接sql,容易sql註入 -->
     <!-- ${}  接受參數的內容,如果傳入類型是簡單類型  ${} 只能使用value -->
     <select id="findByName" parameterType="java.lang.String" resultType="com.MrChengs.po.User" >
           select * from user where username Like ‘%${value}%‘
     </select>
在這裏測試時,‘%${value}%‘,其余字符得不到結果,只能使用value 測試代碼test.java中:
//根據用戶名稱來模糊查詢用戶
     @Test
public void findUserByName() throws IOException{
           
           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);
           
           //創建會話工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     
           //通過工程得到Session
           SqlSession session = sessionFactory.openSession();
           
           //通過SqlSession操作數據庫
           //selectList(String arg0, Object arg1)
           //list中的user和映射文件中的resultType所指類型一直
           List<User> users = session.selectList("test.findByName", "小明");
           for(User user : users){
                System.out.println(user);
           }

此時此刻,沒有使用 %

結果:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 213193302.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - ==>  Preparing: select * from user where username Like ‘%小明%‘
DEBUG [main] - ==> Parameters:
DEBUG [main] - <==      Total: 3
User [id=16, username=張小明, birthday=null, sex=1, address=河南鄭州]
User [id=22, username=陳小明, birthday=null, sex=1, address=河南鄭州]
User [id=25, username=陳小明, birthday=null, sex=1, address=河南鄭州]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - Returned connection 213193302 to pool.
此時是直接拼串,沒有占位符,這種方法的使用,容易被註入! 查詢小結: 1. parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中。 resultType:指定輸出結果類型,mybatis將sql查詢結果的一行記錄數據映射為resultType指定類型的對象。 2. selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常: selectList可以查詢一條或多條記錄。 3. #{} & ${} #{}表示一個占位符號,通過#{}可以實現preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換,#{}可以有效防止sql註入。 #{}可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。 ${}表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換, ${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value ----------------------------------------------------華麗的分割線---------------------------------------------------- 添加用戶: 在在User,xml文件中: 主鍵id是自增的,此時也可以省略主鍵
    <!-- 添加用戶 -->
     <!-- parameterType:指定輸入的參數類型是pojo(包括用戶信息) -->
     <!-- #{} 中指定pojo的屬性名,接收到的pojo對象的屬性值,mybatis通過OGNL獲取對象的屬性值 -->
     <insert id="addUser" parameterType="com.MrChengs.po.User">
           insert into user(id,username,birthday,sex,address)
            value(#{id},#{username},#{birthday},#{sex},#{address})
     </insert>
在測試類test.java:
//添加用戶
     @Test
public void addUser() throws IOException{
           String resource = "SqlMapConfig.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
           SqlSession session = sessionFactory.openSession();
           
           //添加的用戶信息
           User user = new User();
           user.setUsername("MrCheng");
           user.setSex(1);
           user.setBirthday(new Date());
           user.setAddress("北京");
           
           session.insert("test.addUser", user);
           
           //需要提交事物
           session.commit();
           //關閉會話
           session.close();
     }

查看結果:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1384722895.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - ==>  Preparing: insert into user(id,username,birthday,sex,address) value(?,?,?,?,?)
DEBUG [main] - ==> Parameters: 0(Integer), MrCheng(String), 2018-10-05 13:09:06.928(Timestamp), 1(Integer), 北京(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Returned connection 1384722895 to pool.

假設我們此時在添加用戶的同時得到主鍵值:

自增主鍵返回: mysql自增主鍵,執行insert提交之前自動生成一個主鍵 通過mysql函數獲取自增主鍵 對之前的代碼進行修改 User.xml文件中:

LAST_INSERT_ID():是mysql的函數,返回auto_increment自增列新記錄id值

     <!-- 添加用戶 -->
     <!-- parameterType:指定輸入的參數類型是pojo(包括用戶信息) -->
     <!-- #{} 中指定pojo的屬性名,接收到的pojo對象的屬性值,mybatis通過OGNL獲取對象的屬性值 -->
     <insert id="addUser" parameterType="com.MrChengs.po.User">
     
           <!-- 將插入的數據主鍵返回,返回到user對象中 -->
           <!-- SELECT LAST_INSERT_ID():得到insert插入後得到的主鍵值 -->
           <!-- keyProperty:將查詢到的主鍵設置到parameterType指定對象的屬性中 -->
           <!-- order:執行順序,相對比插入insert來說 -->
           <!-- resultType:指定結果的類型 -->
           <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
                SELECT LAST_INSERT_ID()
           </selectKey>
     
           insert into user(id,username,birthday,sex,address)
            value(#{id},#{username},#{birthday},#{sex},#{address})
     </insert>
測試類test.java中:
@Test
public void addUser() throws IOException{
           String resource = "SqlMapConfig.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
           SqlSession session = sessionFactory.openSession();
           User user = new User();
           user.setUsername("MrCheng");
           user.setSex(1);
           user.setBirthday(new Date());
           user.setAddress("北京");
           
           session.insert("test.addUser", user);
           
           System.out.println(user.getId());
           //需要提交事物
           session.commit();
           
                     
           //關閉會話
           session.close();
     }

結果:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: insert into user(id,username,birthday,sex,address) value(?,?,?,?,?)
DEBUG [main] - ==> Parameters: 0(Integer), MrCheng(String), 2018-10-05 14:11:48.735(Timestamp), 1(Integer), 北京(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - ==>  Preparing: SELECT LAST_INSERT_ID()
DEBUG [main] - ==> Parameters:
DEBUG [main] - <==      Total: 1
28
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Returned connection 22429093 to pool.

非自增主鍵的返回: 使用mysql的uuid()函數生成逐漸,需要修改表中的id為String,長度設置為35位
需要增加通過select uuid()得到uuid值
<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE"
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address)
 values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
註意這裏使用的order是“BEFORE”

  

----------------------------------------------------華麗的分割線----------------------------------------------------

刪除用戶:

映射文件中: User.xml文件:
<!-- 刪除用戶 -->
     <!-- 根據id刪除 -->
     <delete id="deleteUser" parameterType="java.lang.Integer">
           delete from user where id=#{id}
     </delete>

測試類:

    //刪除用戶
    @Test
     public void deleteUser() throws IOException{

                String resource = "SqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

                SqlSession session = sessionFactory.openSession();
                
                session.delete("test.deleteUser", 28);
                //需要提交事物
                session.commit();
                //關閉會話
                session.close();
           }

控制臺:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: delete from user where id=?
DEBUG [main] - ==> Parameters: 28(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Returned connection 22429093 to pool.

----------------------------------------------------華麗的分割線----------------------------------------------------

更新數據:

User.xml

    <!-- 更新用戶 -->
     <!-- 根據id更新用戶 -->
     <!-- parameterType:指定user對象,包括id更新信息,註意id必須存在 -->
     <update id="updateUser" parameterType="com.MrChengs.po.User">
           update user set username=#{username},sex=#{sex} where id = #{id}
     
     </update>

測試類:

          //更新
           @Test
           public void updateUser() throws IOException{
                String resource = "SqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                SqlSession session = sessionFactory.openSession();
                User user = new User();
                user.setUsername("MrChegns");
                user.setSex(2);
                user.setId(27);
                session.update("test.updateUser", user);
                //需要提交事物
                session.commit();
                           
                //關閉會話
                session.close();
           }
註意:id必須要上進行設置。 控制臺:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: update user set username=?,sex=? where id = ?
DEBUG [main] - ==> Parameters: MrChegns(String), 2(Integer), 27(Integer)
DEBUG [main] - <==    Updates: 1

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定義輸出結果的類型。

當你看到這裏,基本入門程序已經講解完了!!!

MyBatis(2)增刪改查