@[toc]
1. ${} 和 #{}的区别
Mybatis中的#{}用于传递查询的参数,用于从dao层传递一个string参数过来(也可以是其他参数),select * from 表名 order by age=#{age}
Mybatis会把这个参数转换成一个字符串。select * from 表名 order by age=”age” 相当于jdbc中的预编译,安全。
${}一般用于order by的后面,Mybatis不会对这个参数进行任何的处理,直接生成了sql语句。例:传入一个年龄age的参数,select * from 表名 order by ${age}
所以首选使用 #{}
但是传递参数为一个以上的时候,需要我们用注解去绑定参数
通过使用 @Param
注解的方式(org.apache.ibatis.annotations.Param)
1 | "select * from seckill order by create_time desc limit #{offset},#{limit}") ( |
2. 传递参数
2.1 第一种
通过#{0},#{1} 方式,#{0} 代码第一个参数,#{1} 代码第二个参数
1 | public Good selectGood(String id, String name); |
xml
1 | <select id="selectGood" resultMap="GoodMap"> |
2.2 第二种
通过固定参数的方式
java
1 | public Good selectGood(@param("id")String id,@param("name")String name); |
xml
1 | <select id="selectGood" resultMap="GoodMap"> |
2.3 第三种
通过Map集合去传递(推荐)
java
1 | public Good selectGood(){ |
xml
1 | <select id="selectGood" resultMap="GoodMap"> |
3. 开启驼峰命名规范
1 | //在application.properties中设置 |
如果不设置需要手动在查询的时候设置:
1 | "select * from seckill") ( |
4. 设置扫描包路径
1 | //application.properties中设置 |
如果不设置可以在启动类中手动设置
1 |
|
5. 联表查询
1 | /** |
6. 事务
事务方法的执行时间要尽可能短,不要穿插一些网络操作(RPC/HTTP)请求,如果必须需要,那么将这些网络操作剥离出来(定义一个网络操作方法,将拿到的数据再传递给此事务方法)
不是所有的方法都需要事务,比如: 只有一条修改操作,或只有 只读操作
一般都是读操作和写操作要在同一个方法中时需要申明事务
6.1 添加事务
- 在xml中配置
1 | <!-- 配置事务管理器 --> |
- 在方法中添加注解
@Transactional
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
throws SeckillException, RepeatkillException, SeckillCloseException {
if (md5==null||!md5.equals(MD5Util.getMD5(seckillId))) {
throw new SeckillException("MD5值不合法");
}
try {
//执行秒杀,减少库存
Date nowTime = new Date();
int updateCount = seckillMapper.reduceNumber(seckillId, nowTime);
if (updateCount<=0) {
//没有更新到记录,秒杀结束
throw new SeckillCloseException("秒杀结束");
}else {
//记录购买行为
int insertCount = successKilledMapper.insert(seckillId, userPhone);
if (insertCount<=0) {
//重复插入(主键为seckill和userphone联合主键)
//返回0,重复秒杀
throw new RepeatkillException("重复秒杀");
}else {
//返回1,秒杀成功
SuccessKilled successKilled = successKilledMapper.queryByIdWithSeckill(seckillId, userPhone);
return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS,successKilled);
}
}
}catch (SeckillCloseException e1) {
throw e1;
}catch (RepeatkillException e2) {
throw e2;
}
catch (Exception e) {
logger.error(e.getMessage(),e);
//所有编译期异常 转换为了运行期异常
throw new SeckillException("seckill inner error:"+e.getMessage());
}
}
6.2 事务回滚
spring默认当方法抛出运行期异常的时候会回滚事务
所以我们一般要将编译期异常转化为运行期异常
1 |
|
SeckillException是我们自定义的运行期异常,主要是处理各种业务异常
1 | package com.pibigstar.exception; |
7. 插入返回主键
第一种:
加入这两个属性:useGeneratedKeys="true" keyProperty="id"
1
2
3
4<insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.pibigstar.User">
insert into user(userName,password,comment)
values(#{userName},#{password},#{comment})
</insert>第二种
1
2
3
4
5
6
7<insert id="insertProduct" parameterType="com.pibigstar.model.User" >
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(userName,password,comment)
values(#{userName},#{password},#{comment})
</insert>
order为AFTER
表示插入之后再进行查询一次
1 | <selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id"> |