MyBaits操作数据库之CRUD
向前我们已经快速搭建了一个MyBatis项目,能够对数据库中的数据进行查询操作,接下来我们相对上边的项目的几个点做一些说明,然后进一步学习使用MyBatis对数据库进行CRUD操作
1、 几点说明
1.测试代码的大概执行流程
在测试代码中,我们的SqlSession调用getMapper()方法,方法中传入的是接口类,该方法会到MyBatis-config.xml中找到与之对应的Mapper并返回,至此我们可以通过得到的Mapper对象进行数据库操作方法的调用,这里调用方法的名字与Mapper中namesapce的名字一致,也与接口中的方法名字一致,具体底层代码实现可能与解释不同,现在暂且这么理解即可。流程图如下:
2.namespace和id
在Mapper.xml中,namespace的名字是接口全类名,绑定的是一个接口,如UserMapper.xml中我们的namespace为"com.bjut.dao.UserMapper"
其实这里的xxxMapper.xml相当于之前的接口实现类:xxxImpl.java,这里的UserMapper就相当于之前的xxxDao.java;Mapper.xml中数据库执行命令的id为接口中的方法名。可以像下图这么理解:
对照上述的图,这下应该对xxxDao.java与xxxMapper.java的关系;xxxDaoImpl.java与xxxMapper.xml的关系以及Mapper中namespace和sql的id的命名有了深刻的理解了吧。
上述均为个人理解,用于加深记忆,具体底层实现,随着学习的深入后期再阅读源码更新。
接下来进入今天的主题,使用MyBatis对数据库进行CRUD的操作(基础的操作)
2、 MyBatis进行CRUD(基础操作)
以下sql查询语句的配置均在xxxMapper.xml中进行,代码的修改在xxxMapper.java接口中进行,测试代码使用的是Junit单元测试
1、select 查询语句
- id:对应的接口中的方法名
- resultType:SQL语句执行的返回值
- parameterType:参数类型
全查询,不需要传递参数,返回结果为所有记录,每条记录对应的是一个java类,这里要保持类的属性名与查询结果的列名一致,后续两字段名不同的操作另行说明:
<select id="getUserList" resultType="com.bjut.pojo.User">
select * from mybatis.user;
</select>
// 查询所有用户
List<User> getUserList();
@Test
public void test(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 第二步:获取mapper对象,并执行查询
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<User> userList = mapper.getUserList();
for (User user: userList) {
System.out.println(user.toString());
}
}catch(Exception e){
e.printStackTrace();
}finally {
// 第三步:关闭sqlSession
sqlSession.close();
}
}
条件查询,根据传进来的条件进行数据查询
<select id="getUserByID" resultType="com.bjut.pojo.User" parameterType="int">
select * from mybatis.user where id=#{id}
</select>
// 根据ID查询用户
User getUserByID(int id);
@Test
public void test2(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 第二步:获取mapper对象,并执行查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserByID(1);
System.out.println(user.toString());
}catch(Exception e){
e.printStackTrace();
}finally {
// 第三步:关闭sqlSession
sqlSession.close();
}
}
2、insert插入记录
- id:对应的接口中的方法名
- parameterType:参数类型
- insert默认会返回一个整数,即受影响的数据条数
插入单条数据记录
<!--对象中的属性可以直接取出来使用-->
<insert id="addUser" parameterType="com.bjut.pojo.User">
insert into mybatis.user(id,name,password) values (#{id},#{name},#{password});
</insert>
// 插入一个用户
int addUser(User user);
@Test
public void test3(){
// 获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 获取mapper对象,并执行查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(4,"花生的斯努比","123456");
int i = mapper.addUser(user);
if(i != 0){
System.out.println("插入成功");
}
// 提交事务
sqlSession.commit();
}catch(Exception e){
// 事务回滚
sqlSession.rollback();
e.printStackTrace();
}finally {
// 关闭sqlSession
sqlSession.close();
}
}
插入多条记录
<insert id="addUserList" parameterType="java.util.List">
insert into mybatis.user(id,name,password) values
<foreach collection="list" item="user" separator=",">
(#{user.id},#{user.name},#{user.password})
</foreach>
</insert>
// 插入一组用户
int addUserList(List<User> userList);
@Test
public void test4(){
// 获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 获取mapper对象,并执行查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = new User(5,"花生的斯努比1","123456");
User user2 = new User(6,"花生的斯努比2","123456");
User user3 = new User(7,"花生的斯努比3","123456");
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
userList.add(user3);
int i = mapper.addUserList(userList);
if(i != 0){
System.out.println("批量插入成功");
}
// 提交事务
sqlSession.commit();
}catch(Exception e){
// 事务回滚
sqlSession.rollback();
e.printStackTrace();
}finally {
// 关闭sqlSession
sqlSession.close();
}
}
补充:
- 在进行批量插入时突然想到一个好的东西,就是为什么要在项目中使用log4j,通过使用log4j我们可以查看预编译的sql语句,并根据sql语句的错误进行语句的修改,以及判断是否使用了缓存(后便会讲),如下所示:
[com.bjut.dao.UserMapper.addUserList]-==> Preparing: insert into mybatis.user(id,name,password) values (?,?,?) , (?,?,?) , (?,?,?)
[com.bjut.dao.UserMapper.addUserList]-==> Parameters: 5(Integer), 花生的斯努比1(String), 123456(String), 6(Integer), 花生的斯努比2(String), 123456(String), 7(Integer), 花生的斯努比3(String), 123456(String)
[com.bjut.dao.UserMapper.addUserList]-<== Updates: 3
- 增删改需要提交事务,否则不会插入到数据库,提交事务那么就有事务回滚
sqlSession.commit(); // 提交事务
sqlSession.rollback(); // 事务回滚
3、update更新记录
- id:对应的接口中的方法名
- parameterType:参数类型
- update默认会返回一个整数,即受影响的数据条数
<update id="updateUser" parameterType="com.bjut.pojo.User">
update mybatis.user set name=#{name}, password=#{password} where id=#{id};
</update>
// 更新用户信息
int updateUser(User user);
@Test
public void test5(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 第二步:获取mapper对象,并执行查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(5,"花生的斯努比01","12345678");
int i = mapper.updateUser(user);
if(i != 0){
System.out.println("更新记录成功");
}
sqlSession.commit();
}catch(Exception e){
sqlSession.rollback();
e.printStackTrace();
}finally {
// 第三步:关闭sqlSession
sqlSession.close();
}
}
4、delete删除记录
- id:对应的接口中的方法名
- parameterType:参数类型
- delete默认会返回一个整数,即受影响的数据条数
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
// 删除一条用户信息
int deleteUser(int id);
@Test
public void test6(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 第二步:获取mapper对象,并执行查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deleteUser(6);
if(i != 0){
System.out.println("删除记录成功");
}
sqlSession.commit();
}catch(Exception e){
sqlSession.rollback();
e.printStackTrace();
}finally {
// 第三步:关闭sqlSession
sqlSession.close();
}
}
小结、
- 通过上面的操作我们可以发现,使用mybatis对数据库进行增删改查新业务的添加时,我们只涉及到三个文件的修改:xxxMapper.xml、xxxMapper.java以及对应的测试类,其他内容不需要进行改动。
- 这里我们便可以发现使用mybatis的好处:sql语句和代码分离,我们只需在绑定的接口中添加想要的抽象方法,然后在接口对应的xml文件中编写对应的sql语句即可,各司其职,方便管理。
- 需要强调的是,在进行增删改的操作时,需要添加事务的提交,此外记得关闭SqlSession.
- namespace使用的是绑定接口的全类名
- 标签不要匹配错,标签中只能编写select语句