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.实现删除操作

  1. 删除类实现,根据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 非自定义别名:

  1. jdk中的所有类都使用了非自定义别名,别名内容是类名(不区分大小写)。例如,java.util.Map可以简写成map。

  2. 非自定义别名不需要我们在配置文件中定义。

  3. 如果是包装类(例如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片段可以供不同程序共享使用。