1.實現插入操作
1.1 基本插入操作:
1.先實現最簡單的插入操作(不考慮foreign key情況)。先創建測試表:
test_order_detail_mm.sql:
CREATE TABLE `test_order_detail_mm` ( `id` int(20) NOT NULL AUTO_INCREMENT, `order_id` int(20) NOT NULL, `goods_name` varchar(50) DEFAULT NULL, `single_price` decimal(19,2) DEFAULT NULL, `num` int(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
創建對應實體類TestOrderDetailMm.java,駝峯模式創建屬性和get、set方法。
2.mapper文件,TestOrderDetailMm.xml:
<insert id="addOrderDetail" parameterType="com.vip.model.TestOrderDetailMm" useGeneratedKeys="true" keyProperty="id"> insert into test_order_detail_mm (order_id,goods_name,single_price,num) values (#{orderId},#{goodsName},#{singlePrice},#{num}) </insert>
解釋:
輸入參數是實體類TestOrderDetailMm;useGeneratedKeys表示mybatis使用mysql的jdbc的自增字段的方法來獲得,默認是false的;keyProperty表示設置java類中用來接收getGeneratedKeys、selectKey返回的key的屬性,設置java哪個屬性來接收key值。
3.測試類:
@Test public void testSimpleInsert() { //構建需要創建的記錄(對象),自增字段不管。 TestOrderDetailMm todm = new TestOrderDetailMm(); todm.setOrderId(1); todm.setGoodsName("衣服"); todm.setSinglePrice(198.5); todm.setNum(2); SqlSession session = sqlSessionFactory.openSession(); try { int count = session.insert("com.vip.mapping.TestOrderDetailMm.addOrderDetail", todm); } catch (Exception e) { e.printStackTrace(); session.rollback(); } session.commit(); session.close(); }
必須要設置事務提交,數據才能順利的插入庫中。如果發生錯誤,在catch中回滾事務。
1.2 主外鍵關係插入操作:
在實際應用中,我們有一張訂單表(test_order_mm)和一張訂單明細表(test_order_detail_mm),兩張表通過order表的id連接,當新增一個訂單時(該訂單中也包含訂單明細),需要先插入訂單表,這時候生成一個訂單id,再將該id取過來增加訂單明細信息,該需求的實現如下:
(1)首先,需要定義order和orderDetail各自的mapper文件:
order_detail的mapper:
<insert id="addOrderDetail" parameterType="com.vip.model.TestOrderDetailMm" useGeneratedKeys="true" keyProperty="id"> insert into test_order_detail_mm (order_id,goods_name,single_price,num) values (#{orderId},#{goodsName},#{singlePrice},#{num}) </insert
order的mapper:
<insert id="addOrder" parameterType="com.vip.model.TestOrderMm"> <selectKey keyProperty="id" resultType="int" order="AFTER" > SELECT LAST_INSERT_ID() </selectKey> insert into test_order_mm (order_no,order_address,price,person_id) values (#{orderNo},#{orderAddress},#{price},#{personId}) </insert>
上邊,我們看到了<selectKey>標籤,該標籤可以將標籤內SELECT字句的值返回給TestOrderMm對象的id屬性中。order屬性:先插入再返回id值;還是先返回id值,再插入。
(2)下面定義測試方法:
@Test public void testComplexInsert() { SqlSession session = sqlSessionFactory.openSession(); //構建需要創建的訂單記錄: TestOrderMm t1 = new TestOrderMm(); t1.setOrderNo("00066"); t1.setOrderAddress("NewYork"); t1.setPrice(2321); t1.setPersonId(2); try{ session.insert("com.vip.mapping.TestOrderMm.addOrder", t1); TestOrderDetailMm todm = new TestOrderDetailMm(); todm.setGoodsName("notebook"); todm.setNum(1); todm.setOrderId(t1.getId()); todm.setSinglePrice(2321); session.insert("com.vip.mapping.TestOrderDetailMm.addOrderDetail", todm); }catch (Exception e) { e.printStackTrace(); session.rollback(); } session.commit(); session.close(); }
上邊程序中,先定義order對象類,執行order的insert語句,這時會把mysql自動生成的id返回給t1對象的id屬性。之後我們再構建order_detail對象,setOrderId時,使用todm.setOrderId(t1.getId())。最後再執行order_detail的insert語句,這樣就可以完成上邊敘述的需求了。
(3)執行結果:
DEBUG - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@7ce3cb8e] DEBUG - ==> Preparing: insert into test_order_mm (order_no,order_address,price,person_id) values (?,?,?,?) DEBUG - ==> Parameters: 00066(String), NewYork(String), 2321.0(Double), 2(Integer) DEBUG - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@7ce3cb8e] DEBUG - ==> Preparing: SELECT LAST_INSERT_ID() DEBUG - ==> Parameters: DEBUG - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@7ce3cb8e] DEBUG - ==> Preparing: insert into test_order_detail_mm (order_id,goods_name,single_price,num) values (?,?,?,?) DEBUG - ==> Parameters: 10(Integer), notebook(String), 2321.0(Double), 1(Integer)
程序執行陳宮,我們可以看到使用這種方法生成的sql都是預編譯的,可以防止sql注入問題。最後一步的insert我們獲得了上一步自動生成的order_id 10。
2.實現修改操作
1.修改操作比較簡單,跟insert操作類似,在輸入參數對象時,需要設定id了(確定要修改哪一個)。
mapper文件,TestOrderDetailMm.xml:
<update id="UpdateOrderDetail" parameterType="com.vip.model.TestOrderDetailMm" > Update test_order_detail_mm SET order_id = #{orderId}, goods_name = #{goodsName}, single_price = #{singlePrice}, num = #{num} WHERE id = #{id} </update>
2.測試文件:
@Test public void testSimpleUpdate() { //需要設置逐漸id TestOrderDetailMm todm = new TestOrderDetailMm(); todm.setId(7); todm.setOrderId(4); todm.setGoodsName("智能手錶"); todm.setSinglePrice(2498); todm.setNum(1); SqlSession session = sqlSessionFactory.openSession(); try { int count = session.update("com.vip.mapping.TestOrderDetailMm.UpdateOrderDetail", todm); } catch (Exception e) { e.printStackTrace(); session.rollback(); } session.commit(); session.close(); }
(1)上邊代碼中,在初始化參數對象todm時,這時候,需要setId,把逐漸也set上。
(2)上邊代碼有不好的地方,就是在new參數對象時,需要set每一個屬性值,否則就會將數據庫中的記錄set成null值,最好是先讀出來再update。
3.實現刪除操作
刪除類實現,根據id字段來刪除數據的邏輯:
mapper文件:
<delete id="DeleteOrderDetail" parameterType="java.lang.Integer"> Delete from test_order_detail_mm where id = #{id} </delete>
因爲參數只是一個integer的變量,而不是對象,所以#{}內可以是任意的字符串,不一定是id。
測試類:
@Test public void testDelete() { SqlSession session = sqlSessionFactory.openSession(); try { int count = session.delete("com.vip.mapping.TestOrderDetailMm.DeleteOrderDetail", 4); } catch (Exception e) { e.printStackTrace(); session.rollback(); } session.commit(); session.close(); }
4.Mybatis使用別名:
4.1 自定義別名:
1. 別名需要在根目錄的配置文件sqlMapConfig.xml中定義,在標籤<configuration>下一級,使用標籤typeAliases。
2. 要定義的別名必須是一個數據類型。例如parameterType或resultType等指定的類型,一定不能爲id值指定別名。
如下例所示:
<typeAliases> <typeAlias type="com.vip.model.TestOrderDetailMm" alias="TestOrderDetailMm"></typeAlias> </typeAliases>
type:準備要被取別名的數據類型;
alias:數據類型被取的別名。
3.這個功能可以減少我們的代碼輸入量。
4.2 非自定義別名:
jdk中的所有類都使用了非自定義別名,別名內容是類名(不區分大小寫)。例如,java.util.Map可以簡寫成map。
非自定義別名不需要我們在配置文件中定義。
如果是包裝類(例如java.lang.Integer、java.lang.Character),還可以使用其基本數據類型的名字。例如,java.lang.Integer可以直接簡寫成“int”。
這部分內容比較簡單,可以自行測試。
4.3 定義sql片段:
1.sql片段是一段代碼,這段代碼,很多程序可以共用。
下面程序片段,定義在mapper文件中<mapper>下一級標籤:
<sql id="colums"> id,order_id,goods_name,single_price,num </sql> <select id="selectOrderDetail" resultMap="com.vip.model.TestOrderDetailMm"> select <include refid="colums"/> from test_order_detail_mm </select>
(1)定義sql片段使用sql標籤,id指定sql片段的id;
(2)其中<include>標籤,可以引用sql片段,refid屬性指定的是sql片段的id;
(3)sql片段可以供不同程序共享使用。