这是Mybatis由浅入深的第2节,上文传送门:【Mybatis由浅入深 -01入门】
以下为基础前置条件:请参考其它博文自行安装。
CREATE TABLE `user` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`age` tinyint(1) UNSIGNED NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
insert into `user` VALUES (1,'天罡gg',18);
在UserMapper.java接口新增一个方法:
int insert(User user);
在UserMapper.xml中插入insert节点,一般指定id(像使用雪花算法等 )的插入是这样的:
<insert id="insert" parameterType="com.tiangang.dao.po.User">
insert into user (id, name, age)
values (#{id}, #{name}, #{age})
</insert>
如果不指定id, 插入后如何获得自增id值?
<insert id="insert" parameterType="com.tiangang.dao.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user (name, age)
values (#{name}, #{age})
</insert>
说明:现在一般公司都是遵循阿里规范,id是自增列,插入以后要拿到id,所以推荐做法就是在insert节点增加一个selectKey节点,在order=“after” 时将自增id值设置到keyProperty列。
面试常考点: #{} 是参数占位符, #{id}就是id的占位符,会解析为JDBC预编译语句, 可以防sql注入(就像使用JDBC的?一样); 是字符串替换,不防sql注入,在SQL语句中直接插入一个不转义的字符串,一般用在代替表名列名场景。例如:按列名排序:select∗fromuserorderby {age}, 按任意列查询:select * from user where
@Test
public void insertTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行insert
User user = new User();
user.setName("天罡666");
user.setAge(28);
int rows = mapper.insert(user);
System.out.println("受影响行数:" + rows);
System.out.println("新插入User:" + user);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
sqlSession.close();
}
}
插入成功截图:
同理,在UserMapper.java接口新增一个方法:
int updateById(User user);
同理,在UserMapper.xml中插入update节点
<update id="updateById" parameterType="com.tiangang.dao.po.User">
update user
set name = #{name},
age = #{age}
where id = #{id}
</update>
@Test
public void updateByIdTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行update
User user = new User();
user.setId(2L);
user.setName("天罡666");
user.setAge(38);
int rows = mapper.updateById(user);
System.out.println("受影响行数:" + rows);
System.out.println("修改后的User:" + user);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
sqlSession.close();
}
}
执行结果如下图:
同理,在UserMapper.java接口新增一个方法:
int deleteById(Long id);
同理,在UserMapper.xml中插入delete节点
<delete id="deleteById" parameterType="java.lang.Long">
delete from user
where id = #{id}
</delete>
@Test
public void deleteByIdTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行delete
int rows = mapper.deleteById(2L);
System.out.println("受影响行数:" + rows);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
sqlSession.close();
}
}
执行结果如下图:
为了演示需要,新插入User:User{id=3, name=‘天罡666’, age=28}
在UserMapper.java接口新增方法如下:
// 必会查询场景1:查询1个结果, 返回单个User
User selectById(int id);
// 必会查询场景2:查询N个结果, 返回结果List
List<User> selectListByName(String name);
// 必会查询场景3:根据N个参数(@Param指定参数名),查询N个结果,返回结果List
List<User> selectListByNameAge(@Param("name") String name, @Param("gleAge") Integer gleAge);
// 必会查询场景4:使用${} 进行任意列查询。另外,多个参数未指定@Param的使用
List<User> selectByAnyOneColumn(String columnName, String symbol, String value);
// 必会查询场景5:使用${} 进行order by
List<User> selectAll(String orderBy);
在UserMapper.xml中插入5个select节点
<select id="selectById" resultType="com.tiangang.dao.po.User">
select * from user where id = #{id}
</select>
<select id="selectListByName" resultType="com.tiangang.dao.po.User">
select * from user
where name like concat ('%', #{name},'%')
</select>
<select id="selectListByNameAge" resultType="com.tiangang.dao.po.User">
select * from user
where name like concat ('%', #{name},'%') and age>=#{gleAge}
</select>
<select id="selectByAnyOneColumn" resultType="com.tiangang.dao.po.User">
select * from user
where ${arg0} ${arg1} #{arg2}
</select>
<select id="selectAll" resultType="com.tiangang.dao.po.User">
select * from user order by ${orderBy}
</select>
@Test
public void selectByIdTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行select
User user = mapper.selectById(1);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void selectListByNameTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行select
List<User> userList = mapper.selectListByName("天罡");
System.out.println(userList);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void selectListByNameAgeTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行select
List<User> userList = mapper.selectListByNameAge("天罡", 1);
System.out.println(userList);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void selectByAnyOneColumnTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行select
List<User> userList = mapper.selectByAnyOneColumn("name", "=", "天罡666");
System.out.println(userList);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void selectAllTest() {
// 1. 打开SqlSession
SqlSession sqlSession = MyBatisManager.openSession();
try {
// 2. 得到UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3. 执行select
List<User> userList = mapper.selectAll("age");
System.out.println(userList);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
细心的小伙伴可能已经发现多了一个MyBatisManager类,如果看了上文,就知道SqlSessionFactory应该是全局唯一的,所以我们将它封装到了MyBatisManager.getSqlSessionFactory方法中(使用单例模式),并向外提供了MyBatisManager.openSession,屏蔽了内部实现,使用方只需要每次调用openSession即可,你Get到了吗?
public class MyBatisManager {
private static volatile SqlSessionFactory sqlSessionFactory = null;
public static SqlSessionFactory getSqlSessionFactory() {
// double check 双重检查, 保证SqlSessionFactory全局只创建一次
if (sqlSessionFactory == null) {
synchronized (MyBatisManager.class) {
if (sqlSessionFactory == null) {
String resource = "mybatis-config.xml";
try {
Reader reader = Resources.getResourceAsReader(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return sqlSessionFactory;
}
public static SqlSession openSession() {
return getSqlSessionFactory().openSession();
}
}
这节看似非常简单,实则非常考验基础,很多知识点相信有几年工作经验的人依然傻傻弄不清楚,
如有不到之处,敬请指正!
另外,源码中在单元测试类中CRUD做了简单的封装,新加了 UserMapperTest02Better.java,与UserMapperTest02.java测试功能一致,只是使用executeUserMapperMethod方法简化了代码,不作赘述,详细请见源码:https://download.csdn.net/download/scm_2008/86509214
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有