-
Notifications
You must be signed in to change notification settings - Fork 0
/
mybatis笔记.txt
379 lines (336 loc) · 13.3 KB
/
mybatis笔记.txt
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
1. myBatis的介绍:
MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除
了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索。MyBatis可以使用简单的
XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的
Java对象)映射成数据库中的记录。
jdbc-->dbutil-->(mybatis)-->hibernate
2. mybatis快速入门
a. 添加jar包
mybatis
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
log4j-1.2.16.jar
mybatis-3.1.1.jar
slf4j-api-1.6.2.jar
slf4j-log4j12-1.6.2.jar
mysql驱动
mysql-connector-java-5.1.7-bin.jar
b. 建库+表
create database mybatis;
use mybatis;
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT);
INSERT INTO users(NAME, age) VALUES('Tom', 12);
INSERT INTO users(NAME, age) VALUES('Jack', 11);
c. 在应用的src下添加Mybatis的配置文件conf.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
d. 定义表所对应的实体类
public class User {
private int id;
private String name;
private int age;
}
e. 定义操作users表的sql映射文件userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" parameterType="int" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
f. 在conf.xml文件中注册userMapper.xml文件
<mappers>
<mapper resource="com/atguigu/day03_mybatis/test1/userMapper.xml"/>
</mappers>
g. 编写测试代码:执行定义的select语句
public class Test {
public static void main(String[] args) throws IOException {
String resource = "conf.xml";
//加载mybatis的配置文件(它也加载关联的映射文件)
Reader reader = Resources.getResourceAsReader(resource);
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
//创建能执行映射文件中sql的sqlSession
SqlSession session = sessionFactory.openSession();
//映射sql的标识字符串
String statement = "net.lamp.java.mybatis.bean.userMapper"+".selectUser";
//执行查询返回一个唯一user对象的sql
User user = session.selectOne(statement, 1);
System.out.println(user);
}
}
3. 编写基于mybatis的操作users表的CRUD操作的dao类
a. XML的实现:
1. 定义sql映射xml文件:
<insert id="insertUser" parameterType="net.lamp.java.ibatis.bean.User">
insert into users(name, age) values(#{name}, #{age});
</insert>
<delete id="deleteUser" parameterType="int">
delete from users where id=#{id}
</delete>
<update id="updateUser" parameterType="net.lamp.java.ibatis.bean.User">
update users set name=#{name},age=#{age} where id=#{id}
</update>
<select id="selectUser" parameterType="int" resultType="net.lamp.java.ibatis.bean.User">
select * from users where id=#{id}
</select>
<select id="selectAllUsers" resultType="net.lamp.java.ibatis.bean.User">
select * from users
</select>
2. 在config.xml中注册这个映射文件
<mapper resource="net/lamp/java/ibatis/bean/userMapper.xml"/>
3. 在dao中调用:
public User getUserById(int id) {
SqlSession session = sessionFactory.openSession();
User user = session.selectOne(URI+".selectUser", id);
return user;
}
b. 注解的实现:
1. 定义sql映射的接口
public interface UserMapper {
@Insert("insert into users(name, age) values(#{name}, #{age})")
public int insertUser(User user);
@Delete("delete from users where id=#{id}")
public int deleteUserById(int id);
@Update("update users set name=#{name},age=#{age} where id=#{id}")
public int updateUser(User user);
@Select("select * from users where id=#{id}")
public User getUserById(int id);
@Select("select * from users")
public List<User> getAllUser();
}
2. 在config中注册这个映射接口
<mapper class="net.lamp.java.ibatis.crud.ano.UserMapper"/>
3. 在dao类中调用
public User getUserById(int id) {
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserById(id);
return user;
}
4. 几个可以优化的地方
a. 连接数据库的几个配置可以单独放在一个properties文件中
db.properties
<properties resource="db.properties"/>
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
b. 为实体类定义别名,简化sql映射xml文件中的引用
<typeAliases>
<typeAlias type="net.lamp.java.ibatis.bean.User" alias="_User"/>
</typeAliases>
c. 可以在src下加入log4j的配置文件,打印日志信息(主要是sql语句)
1. log4j.properties
log4j.properties,
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
2. log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="debug" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
5. 解决表的字段名与实体类的属性名不相同的冲突
a. 准备表和数据:
CREATE TABLE orders(
order_id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(20),
order_price FLOAT
);
INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23);
INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33);
INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);
b. 定义实体类:
public class Order {
private int id;
private String orderNo;
private float price;
}
c. 实现getOrderById(id)的查询
c1. 通过在sql语句中定义别名
<select id="selectOrder" parameterType="int" resultType="_Order">
select order_id id, order_no orderNo,order_price price from orders where order_id=#{id}
</select>
c2. 定义<resultMap>
<select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
select * from orders where order_id=#{id}
</select>
<resultMap type="_Order" id="orderResultMap">
<id property="id" column="order_id"/>
<result property="orderNo" column="order_no"/>
<result property="price" column="order_price"/>
</resultMap>
6. 实现联表查询
1). 一对一:
a. 创建表和数据:
CREATE TABLE teacher(
t_id INT PRIMARY KEY AUTO_INCREMENT,
t_name VARCHAR(20)
);
CREATE TABLE class(
c_id INT PRIMARY KEY AUTO_INCREMENT,
c_name VARCHAR(20),
teacher_id INT
);
ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);
INSERT INTO teacher(t_name) VALUES('LS1');
INSERT INTO teacher(t_name) VALUES('LS2');
INSERT INTO class(c_name, teacher_id) VALUES('bj_a', 1);
INSERT INTO class(c_name, teacher_id) VALUES('bj_b', 2);
b. 定义实体类:
public class Teacher {
private int id;
private String name;
}
public class Classes {
private int id;
private String name;
private Teacher teacher;
}
c. 定义sql映射文件ClassMapper.xml:
<!-- 方式一:嵌套查询方式, 通过执行另外一个SQL映射语句来返回预期的复杂类型 -->
<select id="getClasses" parameterType="int" resultMap="ClassesResultMap2">
select * from class where c_id=#{id}
</select>
<resultMap type="CLasses" id="ClassesResultMap2">
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<association property="teacher" javaType="Teacher" column="teacher_id" select="getTeacher"></association>
</resultMap>
<select id="getTeacher" parameterType="int" resultType="Teacher">
select t_id id, t_name name from teacher where t_id=#{id}
</select>
<!--
方式二:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
-->
<select id="getClasses2" parameterType="int" resultMap="ClassesResultMap">
select * from class c,teacher t where c.c_id=#{id} and c.teacher_id=t.t_id;
</select>
<resultMap type="Classes" id="ClassesResultMap">
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<association column="teacher_id" property="teacher" javaType="Teacher">
<id column="t_id" property="id"/>
<result column="t_name" property="name"/>
</association>
</resultMap>
d. 测试:
@Test
public void testQueryOO() {
SqlSession session = factory.openSession();
Classes c = sqlSession.selectOne("com.atguigu.day03_mybatis.test5.CTMapper.getClasses", 1);
System.out.println(c);
}
@Test
public void testQueryOO2() {
SqlSession session = factory.openSession();
Classes c = sqlSession.selectOne("com.atguigu.day03_mybatis.test5.CTMapper.getClasses2", 1);
System.out.println(c);
}
2) 一对多
a. 创建表和数据:
CREATE TABLE student(
s_id INT PRIMARY KEY AUTO_INCREMENT,
s_name VARCHAR(20),
class_id INT
);
INSERT INTO student(s_name, class_id) VALUES('xs_B', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_D', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_E', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_A', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_H', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_J', 2);
b. 定义实体类:
public class Student {
private int id;
private String name;
}
public class Classes {
private int id;
private String name;
private Teacher teacher;
private List<Student> students;
}
c. 定义sql映射文件ClassMapper.xml:(根据classId查询对应的班级信息,包括学生)
<!-- 集合的嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
<select id="getClasses3" parameterType="int" resultMap="ClassesResultMap3">
select * from class c,teacher t, student s where c.c_id=#{id} and c.teacher_id=t.t_id and s.class_id=c.c_id
</select>
<resultMap type="Classes" id="ClassesResultMap3">
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<association column="teacher_id" property="teacher" javaType="Teacher">
<id column="t_id" property="id"/>
<result column="t_name" property="name"/>
</association>
<collection property="students" ofType="Student" javaType="ArrayList">
<id property="id" column="s_id" />
<result property="name" column="s_name"/>
</collection>
</resultMap>
<!-- 集合的嵌套查询方式, 通过执行另外一个SQL映射语句来返回预期的复杂类型 -->
<select id="getClasses4" parameterType="int" resultMap="ClassesResultMap4">
select * from class c where c.c_id=#{id}
</select>
<resultMap type="CLasses" id="ClassesResultMap4">
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<association property="teacher" javaType="Teacher" column="teacher_id" select="getTeacher"></association>
<collection property="students" ofType="Teacher" column="c_id" select="getStudentsSelect" ></collection>
</resultMap>
<select id="getTeacher" parameterType="int" resultType="Teacher">
select t_id id, t_name name from teacher where t_id=#{id}
</select>
<select id="getStudentsSelect" parameterType="int" resultType="Student" >
select s_id id, s_name name from student where class_id=#{id}
</select>
d. 测试:
@Test
public void testQueryOT() {
SqlSession session = factory.openSession();
Classes classes = openSession.selectOne("com.atguigu.day03_mybatis.test6.OMMapper.getClasses3", 1);
System.out.println(c);
}
@Test
public void testQueryOT2() {
SqlSession session = factory.openSession();
Classes classes = openSession.selectOne("com.atguigu.day03_mybatis.test6.OMMapper.getClasses4", 1);
System.out.println(c);
}