MyBatis(2)增刪改查
本次全部學習內容:MyBatisLearning
查: 根據id查詢用戶信息,得到一個用戶信息 在User.xml文件中添加代碼:<mapper namespace="test"> <!-- 配置很多的sql語句 --> <!-- 查詢標簽 --> <!-- id用於唯一標識這個sql查詢 --> <!-- #{} 標識占位符 --> <!-- parameterType:指定輸入參數的類型: --> <!-- #{id}:接受輸入的參數,id表示輸入的參數,參數名就是id,如果輸入參數是簡單的類型,#{}中的參數可以是任意字符 --> <!-- resultType:輸出結果的類型 所映射的java 類型對象,單挑記錄所映射成的java對象-->在測試代碼中test.java:<select id="findUserByID" parameterType="int" resultType="com.MrChengs.po.User"> select * from user where id=#{id} </select> </mapper>
//根據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)增刪改查