Mybatis学习日志二
学习目标
- 能够掌握mybatis中的接口的CRUD
- 能够掌握mybatis中的dao实现类方式的CRUD
- 了解mybatis主配置文件的标签的使用
1 mybatis中的接口的CRUD
通过代理接口来实现CRUD操作
1.1 dao层接口
/**
* 用户持久层接口
*/
public interface IUserDao {
/**
* 查询所有
* @return
*/
List<User> findAll();
/**
* 保持用户
* @param user
*/
void saveUser(User user);
/**
* 更新用户
* @param user
*/
void updateUser(User user);
/**
* 删除用户
* @param userId
*/
void deleteUser(Integer userId);
/**
* 查询用户
* @param userId 输入查询用户的ID
* @return 返回查询对象
*/
User findById(Integer userId);
/**
* 模糊查询用户
* @param uName 根据用户名模糊查询
* @return 模糊查询结果集
*/
List<User> findByName(String uName);
/**
* 查询用户总数
* @return
*/
int findTotal();
}
1.2 关于映射文件配置中的问题
namespace
确定在哪个dao接口
id
是指的哪个方法
resultType
表示我们要将结果集封装到哪里去
parameterType
指的是我们我们方法中传入的参数类型
KeyProperty
指的是实体类中的属性
KeyColumn
指的是数据库中的列名
order
是决定此语句的执行顺序
注意事项:
- values中的参数需用#{}定义,并且在实体类中,有系统生成的get、set方法,#{?} ?必须是实体类中成员变量名称。
- 在id方法里有且只有一个形参,该形参如果是基本类型以及其包装类例如int、Integer…那么Sql语句中的#{?} ?任意字符即可。
/**
* IUserDao.xml
* dao接口的映射配置文件
*/
<mapper namespace="dao.IUserDao">
<!-- 查询所有 -->
<select id="findAll" resultType="domain.User">
select * from user;
</select>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="domain.User">
<!-- 配置插入操作后,获取新插入数据的ID(直接将值拉取到对象中) -->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday});
</insert>
<!-- 更新用户 -->
<update id="updateUser" parameterType="domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{userId};
</delete>
<!-- 查询用户 -->
<select id="findById" parameterType="Integer" resultType="domain.User">
select * from user where id=#{uid}
</select>
<!-- 模糊查询 -->
<select id="findByName" resultType="domain.User" parameterType="String">
select * from user where username like #{uName};<!-- 使用这种方法模糊查询,那么传入的查询条件必须左右自带一个% -->
<!-- select * from user where username like '%${value}%'; value 是固定的,不可以为其他名字 -->
</select>
<!-- 查询用户总数 -->
<select id="findTotal" resultType="int">
select count(id) from user;
</select>
</mapper>
1.3 测试代码及结果
初始化与事务提交并释放资源代码单独实现代码如下:
private InputStream in;
private SqlSession session;
private IUserDao userDao;
/**
* 初始化
* @throws IOException
*/
@Before//用于在测试方法之前执行
public void init() throws IOException {
//1.获取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
session = factory.openSession();
//4.获取代理对象
userDao = session.getMapper(IUserDao.class);
}
/**
* 事务提交并释放资源
* @throws IOException
*/
@After//用于在测试方法之后执行
public void destroy() throws IOException {
//1.提交事务
session.commit();
//2.释放资源
session.close();
in.close();
}
查询所有操作
/**
* 测试查询所有操作
*
* @throws IOException
*/
@Test
public void testFindALL() {
//1.执行查询所有方法
List<User> users = userDao.findAll();
//2.遍历结果集
for (User user : users) {
System.out.println(user);
}
}
保存用户
@Test
public void testSave() {
//1.创建用户
User user = new User();
user.setUsername("牛牛");
user.setAddress("成都");
user.setBirthday(new Date());
user.setSex("男");
System.out.println("保存前ID值:" + user.getId());
//2.执行保存用户方法
userDao.saveUser(user);
System.out.println("保存后ID值:" + user.getId());
}
更新操作
@Test
public void testUpdate() {
//1.确定用户
User user = new User();
//2.确定修改用户的id
user.setId(50);
user.setUsername("mybatis update user");
user.setAddress("成都");
user.setBirthday(new Date());
user.setSex("女");
//3.执行修改用户方法
userDao.updateUser(user);
}
删除用户
@Test
public void testDelete() {
//1.执行删除用户方法
userDao.deleteUser(48);
}
通过ID查询用户
@Test
public void testFindById() {
//1.执行查询用户方法
User user = userDao.findById(50);
System.out.println(user);
}
通过用户名模糊查询
@Test
public void testFindByName() {
//1.执行模糊查询用户方法
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
查询总用户数
@Test
public void testFindTotal() {
//1.执行查询总用户数方法
int count = userDao.findTotal();
System.out.println("总共用户数目为:" + count);
}
2 mybatis中的参数及返回值深入
2.1 参数深入–实体类的包装
OGNL表达式–Object Graphic Navigation Language
对象 图 导航 语言
它是通过对象的取值方法来获取数据。在写法上把get省略了。
geg:我们获取用户的名称
- 类中的写法: user.getUserName();
- OGNL表达式:user.username
mybatis中为什么能直接写username,而不用user.呢?
答:因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名,而是直接写属性名。
实际开发中常常将多个实体类组成一个查询对象进行查询
/**
* 根据queryVo中的条件查询用户
* @param vo
* @return
*/
List<User> findUserByVo(QueryVo vo);
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
<!-- 根据QueryVo的条件查询用户 -->
<select id="findUserByVo" resultType="domain.User" parameterType="domain.QueryVo">
select * from user where username like #{user.username};
</select>
这里的parameterType属性中传入QueryVo对象,那么#{}中填的值是用OGNL表达式,所以user表示QueryVo中的成员变量,用user.username表示User对象中的username。
2.2 返回值的深入–结果类型的封装
当实体类中的属性名称与数据库中列名不同时,查询操作将无法返回至实体类中。(注:Windows系统下mysql列名不分大小写)
解决方法:
- 修改数据库中的列名与之实体类中的属性名一致。
- 定义sql语句时起别名例如:(执行效率提高,后续维护成本高)
select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;
-
映射文件xml中配置 查询结果的列名和实体类的属性名的对应关系。(执行效率低,后续维护效率高)
- 定义一个结果映射
<!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="userMap" type="domain.User"> <!-- 主键字段对应 --> <id property="userId" column="id"></id> <!-- 非主键字段对应 --> <result property="userAddress" column="address"></result> <result property="userSex" column="sex"></result> <result property="userBirthday" column="birthday"></result> </resultMap>
- 此时其他配置中的resultType必须修改成resultMap="userMap"才能起作用。(resultMap中的值是配置结果集的id)
<!-- 查询所有 --> <select id="findAll" resultMap="userMap"> select * from user; </select>
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的类名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
3 mybatis中的dao实现类方式的CRUD
- mybatis 支持开发人员手写dao实现类。
- 实际开发中,通常不写出dao的实现类。
查询所有
@Override
public List<User> findAll() {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用SqlSession中的方法,实现查询列表
List<User> users = session.selectList("dao.IUserDao.findAll");//参数就是能获取到配置信息的key----配置文件中的namespace.方法名
//3.释放资源
session.close();
return users;
}
保存用户
@Override
public void saveUser(User user) {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用方法实现保存
session.insert("dao.IUserDao.saveUser",user);
//3.提交事务
session.commit();
//4.释放资源
session.close();
}
session.insert(String statement , Object parameter);
- statement – 表示哪个配置来支持
- parameter – 这个配置需要的参数是哪个
更新用户
@Override
public void updateUser(User user) {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用方法实现更新
session.update("dao.IUserDao.updateUser",user);
//3.提交事务
session.commit();
//4.释放资源
session.close();
}
删除用户
@Override
public void deleteUser(Integer userId) {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用方法实现删除用户
session.delete("dao.IUserDao.deleteUser",userId);
//3.提交事务
session.commit();
//4.释放资源
session.close();
}
通过ID查询一个用户
@Override
public User findById(Integer userId) {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用SqlSession中的方法,实现查询用户
User user = session.selectOne("dao.IUserDao.findById",userId);
//3.释放资源
session.close();
return user;
}
查询总用户数
@Override
public int findTotal() {
//1.根据Factory获取SqlSession对象
SqlSession session = factory.openSession();
//2.调用SqlSession中的方法,实现查询用户
int count = session.selectOne("dao.IUserDao.findTotal");
//3.释放资源
session.close();
return count;
}
PreparedStatement对象它的执行方法
- execute:它能执行CRUD中的任意一种语句。它的返回值是一个boolean类型,表示是否有结果集。
- executeUpdate:它只能执行CUD语句,查询语句无法执行。它的返回值是影响数据库记录的行数。
- executeQuery:它只能执行SELECT语句,无法执行CUD。执行结果封装的结果集为ResultSet对象。
4 mybatis主配置文件的标签的使用
properties标签:
可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置文件信息。在外部配置数据库信息便于维护。
- resource属性:用于指定配置文件的位置,是按照类路径的写法,且必须存在于类路径下。
- url属性:要求Url的写法来写地址
- URL:Uniform Resource Locator 统一资源定位符。唯一标识一个资源的位置。
- 它的写法:http://localhost:8080/mybatisserver/demo
- URI:Uniform Resource Identifier 统一资源标识符。唯一定位一个资源。
- 它的写法:file:///E:\2021\个人仓库\mybatis\cn_kq_day2\day2_01CRUD\src\main\resources
- URL:Uniform Resource Locator 统一资源定位符。唯一标识一个资源的位置。
typeAliases标签:
配置别名,它只能配置domain中类的别名
- typeAlias 用于配置别名。
- type属性指定的是实体类全限定类名。
- alias属性指定别名。
<typeAliases>
<typeAlias type="domain.User" alias="user"></typeAlias>
</typeAliases>
注:当指定了别名就不再区分大小写
- package 用于指定要配置别名的包
- 当指定之后,该包下的实体类都会注册别名。类名就是别名,不再区分大小写。
<typeAliases>
<package name="domain"/>
</typeAliases>
mappers标签:
-
mapper 指定映射文件的位置
- resource dao接口映射文件的位置
- class dao接口的位置(@注解时使用)
<mappers> <mapper resource="dao/IUserDao.xml"/> </mappers>
-
package 指定dao接口所在的包
- name dao接口包位置所在
- 注:当指定了之后就不需要再写mapper以及resource或者class了。
<mappers> <package name="dao"/> </mappers>
- name dao接口包位置所在
注:两者不能同时写。
源自黑马+自我总结,如有错误之处望指出。