一、基于XML的CRUD操作
前面在入门程序中实现了对数据库中所有数据的查询。接下来就基于入门程序的基础上,实现对数据库数据的CRUD。
(1)修改IUserdao,添加方法。
public interface IUserDao {
/**
* 增加用户
*/
void addUser(User user);
/**
* 删除用户
*/
void deleteById(Integer id);
/**
* 修改用户
*/
void updateUser(User user);
/**
* 查询所有
* @return
*/
List<User> findAll();
}
(2)在userMapper.xml中添加sql语句。
<?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">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IUserDao">
<!-- 添加用户 -->
<insert id="addUser" parameterType="com.day1.entity.User">
insert into t_user(username, password) values(#{username}, #{password});
</insert>
<!-- 删除用户 -->
<delete id="deleteById" parameterType="int">
delete from t_user where id = #{id}
</delete>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="com.day1.entity.User">
update t_user set username =#{username}, password= #{password} where id = #{id}
</update>
<!--
查询所有用户
-->
<select id="findAll" resultType="com.day1.entity.User">
select * from t_user;
</select>
</mapper>
(3)创建测试类CRUDTest。
public class CRUDTest {
InputStream in = null;
SqlSessionFactoryBuilder builder = null;
SqlSessionFactory factory = null;
SqlSession sqlSession = null;
IUserDao userDao = null;
@Before
public void init() throws IOException {
//1、读取配置文件
in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3、使用工厂生产SqlSession对象
sqlSession = factory.openSession();
userDao = sqlSession.getMapper(IUserDao.class);
}
@After
public void destory() throws IOException {
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testInsert(){
User user = new User("宋江", "song123");
userDao.addUser(user);
}
@Test
public void testDelete(){
userDao.deleteById(5);
}
@Test
public void testUpdate(){
User user = new User(5,"宋江", "song123");
userDao.updateUser(user);
}
@Test
public void testFindAll(){
List<User> userList = userDao.findAll();
for(User user : userList){
System.out.println(user);
}
}
}
测试增加数据操作:
测试查询所有,如下:
测试修改数据操作,如下:
测试删除数据, 如下:
基于XML的实现方式中还有另外一种,就是基于接口实现类来完成CRUD,这种方式了解即可,因为实际开发中如果采用这种方式,会增加开发的复杂性和代码量。这里可以演示一下它的使用:
(1)添加IUserDao的实现类UserDaoImpl。
public class UserDaoImpl implements IUserDao {
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public void addUser(User user) {
SqlSession sqlSession = factory.openSession();
sqlSession.insert("com.day1.dao.IUserDao.addUser", user);
}
@Override
public void deleteById(Integer id) {
SqlSession sqlSession = factory.openSession();
sqlSession.delete("com.day1.dao.IUserDao.deleteById", id);
}
@Override
public void updateUser(User user) {
SqlSession sqlSession = factory.openSession();
sqlSession.update("com.day1.dao.IUserDao.updateUser", user);
}
@Override
public List<User> findAll() {
SqlSession sqlSession = factory.openSession();
List<User> list = sqlSession.selectList("com.day1.dao.IUserDao.findAll");
return list;
}
}
(2)创建测试类ImplTest。
public class ImplTest {
InputStream in = null;
SqlSessionFactoryBuilder builder = null;
SqlSessionFactory factory = null;
IUserDao userDao = null;
@Before
public void init() throws IOException {
//1、读取配置文件
in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3、使用IUserDao创建对象
userDao = new UserDaoImpl(factory);
}
@After
public void destory() throws IOException {
in.close();
}
@Test
public void testFindAll(){
System.out.println(userDao.findAll());
}
@Test
public void testInsert(){
User user = new User("吴用","aabbcc");
userDao.addUser(user);
}
@Test
public void testUpdate(){
User user = new User(6, "吴用","123123");
userDao.updateUser(user);
}
@Test
public void testDelete(){
userDao.deleteById(6);
}
}
二、基于注解的CRUD操作
如果基于注解方式实现CRUD,则不需要userMapper文件的存在。
(1)在SqlMapperConfig.xml中配置接口类。
<mappers>
<mapper class="com.day1.dao.IUserDao"></mapper>
</mappers>
(2)修改接口类
public interface IUserDao {
/**
* 增加用户
*/
@Insert("insert into t_user(username, password) values(#{username}, #{password});")
void addUser(User user);
/**
* 删除用户
*/
@Delete("delete from t_user where id = #{id}")
void deleteById(Integer id);
/**
* 修改用户
*/
@Update("update t_user set username=#{username}, password=#{password} where id = #{id}")
void updateUser(User user);
/**
* 查询所有
* @return
*/
@Select("select * from t_user")
List<User> findAll();
}
(3)创建测试类
public class AnnoTest {
InputStream in = null;
SqlSessionFactoryBuilder builder = null;
SqlSessionFactory factory = null;
SqlSession sqlSession = null;
IUserDao userDao =null;
@Before
public void init() throws IOException {
//1、读取配置文件
in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3、使用工厂生产SqlSession对象
sqlSession = factory.openSession();
userDao = sqlSession.getMapper(IUserDao.class);
}
@After
public void destory() throws IOException {
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
System.out.println(userDao.findAll());
}
@Test
public void testInsert(){
User user = new User("吴用","aabbcc");
userDao.addUser(user);
}
@Test
public void testUpdate(){
User user = new User(6, "吴用","123123");
userDao.updateUser(user);
}
@Test
public void testDelete(){
userDao.deleteById(6);
}
}
三、数据的其他操作
前面的两个部分分别介绍了基于XML和基于注解的实现方式,接下来针对数据库操作都将采用XML的方式来完成。
1、查询一条数据
(1)在IUserDao中添加findById(Integer id)方法。
/**
* 根据id查询用户
*/
User findById(Integer id);
(2)在userMapper.xml中添加查询方法。
<!-- 根据id查询用户 -->
<select id="findById" parameterType="Integer" resultType="com.day1.entity.User">
select * from t_user where id = #{id}
</select>
(3)在测试类中添加测试方法。
@Test
public void testFindById(){
User user = userDao.findById(3);
System.out.println(user);
}
执行结果如下:
2、模糊查询
为了实现模糊查询,将在t_user表中插入几条数据。如下:
insert into t_user(username,password) values("张飞","zahngfei");
insert into t_user(username,password) values("张倩","zhangabc");
insert into t_user(username,password) values("张超","1231233");
模糊查询有两种方式,一种是在传参的时候拼接%,而SQL语句内容不变;另一种方式是在sql语句中加入%,即${%value%}。
(1)方式一:使用#{}
这种方式在传入参数的时候需要在参数的前面加上%,而在mapper文件中则无需添加,相当于PreparedStatement,如下:
select * from t_user where username like #{para};
userDao.findUser("%para%")
第一步:在IUserDao中添加方法
/**
* 模糊查询方式一
*/
List<User> findLikeUser01(String name);
第二步:在userMapper.xml中添加sql语句。
<!-- 模糊查询方式一 -->
<select id="findLikeUser01" parameterType="String" resultType="com.day1.entity.User">
select * from t_user where username like #{username}
</select>
第三步:进行测试。
@Test
public void testFindLike01(){
List<User> userList = userDao.findLikeUser01("%张%");
for(User user : userList){
System.out.println(user);
}
}
(2)方式二:使用${}
这种方式需要在语句中添加%,而传递参数时则不需添加%。其实质是底层做了拼接操作,相当于Statement。如下:
select * from t_user where username like ${'%para%'}
userDao.findUser("para")
第一步:在IUserDao中添加方法
/**
* 模糊查询方式二
*/
List<User> findLikeUser02(String name);
第二步:在userMapper.xml中添加sql语句。
<!-- 模糊查询方式二 -->
<select id="findLikeUser02" parameterType="String" resultType="com.day1.entity.User">
select * from t_user where username like '%${value}%'
</select>
第三步:进行测试。
@Test
public void testFindLike02(){
List<User> userList = userDao.findLikeUser02("张");
for(User user : userList){
System.out.println(user);
}
}
(3)两种方式的说明
第一种方式,它的控制台输出语句是这样的:
在前面的实现过程中可以看到在配置文件中并没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标识%。配置文件中的#{username}充当的是占位符的作用,所以 SQL 语句显示为“?”。
第二种方式,它的控制台输出语句是这样的:
这种方式在程序代码中不需要加入模糊查询的匹配符%了,其sql语句相当于做了一个拼串的操作。
(4)#{}和${}的区别
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止 sql 注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是 value 或其它名称,其内容不做限制。
${}表示拼接 sql 串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。其源码如下:
3、获取保存数据的id
当向主键是自增型的数据库表中插入一条记录时,如果期望获取刚刚写入这条记录的id,此时就需要使用select last_insert_id();语句来获取插入记录后返回的自增id的值。使用如下:
(1)修改userMapper.xml中的insert语句
<!-- 添加用户 -->
<insert id="addUser" parameterType="com.day1.entity.User">
<!--
keyProperty:将查询到主键值设置到 parameterType 指定的对象的那个属性
keyColumn:数据库中的列名
order:SELECT LAST_INSERT_ID() 执行顺序,相对于 insert 语句来说它的执行顺序
resultType:指定 SELECTLAST_INSERT_ID() 的结果类型
-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into t_user(username, password) values(#{username}, #{password});
</insert>
参数说明:
keyProperty:将查询到主键值设置到 parameterType 指定的对象的哪个属性。
keyColumn:数据库中的列名。
order:select last_insert_id() 执行顺序,相对于 insert 语句来说它的执行顺序,有AFTER和BEFORE两个取值。
resultType:指定 select last_insert_id()的结果类型。
(2)重新测试insert操作。
@Test
public void testInsert(){
User user = new User("张飞", "feifei");
userDao.addUser(user);
System.out.println(user);
}
执行结果如下: