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片段可以供不同程序共享使用。
转载于:https://blog.51cto.com/6216083/1841179