MyBatis(二)
发布日期:2021-07-22 10:54:11 浏览次数:8 分类:技术文章

本文共 13650 字,大约阅读时间需要 45 分钟。

目录


Mybatis基于代理Dao的CRUD操作                    重点内容

CRUD中可能遇到的问题:参数的传递以及返回值的封装
介绍Mybatis基于传统dao方式的使用(自己编写dao的实现类)    了解的内容
mybatis主配置文件中的常用配置
    properties标签
    typeAliases标签                ---解释Integer的写法
    mappers标签的子标签:package


OGNL表达式:

    Object Graphic Navigation Language
    对象       图          导航            语言
    
    它是通过对象的取值方法来获取数据。在写法上把get给省略了。
    比如:我们获取用户的名称
        类中的写法:user.getUsername();
        OGNL表达式写法:user.username
    mybatis中为什么能直接写username,而不用user.呢:
        因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名

 

 

自定义流程复习

mybatis 环境搭建步骤


MyBatis的CRUD操作

         根据 ID 查询

1
在持久层接口中添加
findById
方法
/*** 根据 id 查询* @param userId* @return*/User findById(Integer userId);

 

2
在用户的映射配置文件中配置
细节:
resultType
属性:
用于指定结果集的类型。
parameterType
属性
传智播客——专注于
Java
.Net
Php
、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
用于指定传入参数的类型。
sql
语句中使用
#{}
字符:
它代表占位符,相当于原来
jdbc
部分所学的
?
,都是用于执行语句时替换实际的数据。
具体的数据是由
#{}
里面的内容决定的。
#{}
中内容的写法:
由于数据类型是基本类型,所以此处可以随意写。
3
在测试类添加测试
/**** 

Title: MybastisCRUDTest

*

Description: 测试 mybatis 的 crud 操作

*

Company: http://www.itheima.com/

*/public class MybastisCRUDTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Testpublic void testFindOne() {//6.执行操作User user = userDao.findById(41);System.out.println(user);}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象userDao = session.getMapper(IUserDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{session.commit();//7.释放资源session.close();in.close();}}

         保存操作

1 在持久层接口中添加新增方法

/*** 保存用户* @param user* @return 影响数据库记录的行数*/int saveUser(User user);
2.2.2
在用户的映射配置文件中配置
insert into user(username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})
细节:
parameterType
属性:
代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
sql
语句中使用
#{}
字符:
它代表占位符,相当于原来
jdbc
部分所学的
?
,都是用于执行语句时替换实际的数据。
具体的数据是由
#{}
里面的内容决定的。
#{}
中内容的写法:
由于我们保存方法的参数是 一个
User
对象,此处要写
User
对象中的属性名称。
它用的是
ognl
表达式。
ognl
表达式:
它是
apache
提供的一种表达式语言,全称是:
Object Graphic Navigation Language
对象图导航语言
它是按照一定的语法格式来获取数据的。
语法格式就是使用
#{
对象
.
对象
}
的方式
#{user.username}
它会先去找
user
对象,然后在
user
对象中找到
username
属性,并调用
getUsername()
方法把值取出来。但是我们在
parameterType
属性上指定了实体类名称,所以可以省略
user.
而直接写
username
3
添加测试类中的测试方法
@Testpublic void testSave(){User user = new User();user.setUsername("modify User property");user.setAddress("北京市顺义区");user.setSex("男");user.setBirthday(new Date());System.out.println("保存操作之前:"+user);//5.执行保存方法userDao.saveUser(user);System.out.println("保存操作之后:"+user);}/*打开 Mysql 数据库发现并没有添加任何记录,原因是什么?这一点和 jdbc 是一样的,我们在实现增删改时一定要去控制事务的提交,那么在 mybatis 中如何控制事提交呢?可以使用:session.commit();来实现事务提交。加入事务提交后的代码如下:*/@After//在测试方法执行完成之后执行public void destroy() throws Exception{session.commit();//7.释放资源session.close();in.close();}

 4 问题扩展:新增用户 id 的返回值

新增用户后,同时还要返回当前新增用户的
id
值,因为
id
是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。
select last_insert_id();
insert into user(username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})

         用户更新

1
在持久层接口中添加更新方法
/*** 更新用户* @param user* @return 影响数据库记录的行数*/int updateUser(User user);
2
在用户的映射配置文件中配置
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
3
加入更新的测试方法
@Testpublic void testUpdateUser()throws Exception{//1.根据 id 查询User user = userDao.findById(52);//2.更新操作user.setAddress("北京市顺义区");int res = userDao.updateUser(user);System.out.println(res);}

          用户删除

1
在持久层接口中添加删除方法
/*** 根据 id 删除用户* @param userId* @return*/int deleteUser(Integer userId);
2
在用户的映射配置文件中配置
delete from user where id = #{uid}
3
加入删除的测试方法
@Testpublic void testDeleteUser() throws Exception {//6.执行操作int res = userDao.deleteUser(52);System.out.println(res);}

         用户模糊查询

1
在持久层接口中添加模糊查询方法
/*** 根据名称模糊查询* @param username* @return*/List
findByName(String username);
2
在用户的映射配置文件中配置
3
加入模糊查询的测试方法
@Testpublic void testFindByName(){//5.执行查询一个方法List
users = userDao.findByName("%王%");for(User user : users){System.out.println(user);}}
在控制台输出的执行
SQL
语句如下:
我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”
 

在使用mybatis的模糊查询时,有两个特殊符号需要注意

  1. %(百分号):相当于任意多个字符;

  2.  
  3. _(下划线):相当于任意的单个字符;

 

4
模糊查询的另一种配置方式
第一步:修改
SQL
语句的配置,配置如下:
我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。第二步:测试,如下:/*** 测试模糊查询操作*/@Testpublic void testFindByName(){//5.执行查询一个方法List
users = userDao.findByName("王");for(User user : users){System.out.println(user);}}
在控制台输出的执行
SQL
语句如下:
 
可以发现,我们在程序代码中就不需要加入模糊查询的匹配符
%
了,这两种方式的实现效果是一样的,但执行的语句是不一样的
5 #{}
${}
的区别
#{}
表示一个占位符号
通过
#{}
可以实现
preparedStatement
向占位符中设置值,自动进行
java
类型和
jdbc
类型转换,
#{}
可以有效防止
sql
注入。
#{}
可以接收简单类型值或
pojo
属性值。 如果
parameterType
传输单个简单类
型值,
#{}
括号中可以是
value
或其它名称。
${}
表示拼接
sql
通过
${}
可以将
parameterType
传入的内容拼接在
sql
中且不进行
jdbc
类型转换,
${}
可以接收简
单类型值或
pojo
属性值,如果
parameterType
传输单个简单类型值,
${}
括号中只能是
value
2.5.6
模糊查询的
${value}
源码分析
TextSqlNode
类的源码:
这就说明了源码中指定了读取的
key 的名字就是”value”
,所以我们在绑定参数时就只能叫
value
的名字

 

         查询使用聚合函数

1
在持久层接口中添加模糊查询方法
/*** 查询总记录条数* @return*/int findTotal();
2
在用户的映射配置文件中配置
3
加入聚合查询的测试方法
@Testpublic void testFindTotal() throws Exception {//6.执行操作int res = userDao.findTotal();System.out.println(res);}

         传递 pojo 包装对象

开发中通过
pojo
传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo 类中包含 pojo
需求:根据用户名查询用户信息,查询条件放到
QueryVo
user
属性中。
1
编写
QueryVo
/**** 

Title: QueryVo

*

Description: 查询条件对象

*

Company: http://www.itheima.com/

*/public class QueryVo implements Serializable {private User user;public User getUser() {return user;}public void setUser(User user) {this.user = user;}}
2
编写持久层接口
/**** 

Title: IUserDao

*

Description: 用户的业务层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 根据 QueryVo 中的条件查询用户* @param vo* @return*/List
findByVo(QueryVo vo);}
3
持久层接口的映射文件
4
测试包装类作为参数
@Testpublic void testFindByQueryVo() {QueryVo vo = new QueryVo();User user = new User();user.setUserName("%王%");vo.setUser(user);List
users = userDao.findByVo(vo);for(User u : users) {System.out.println(u);}}

 Mybatis 的输出结果封装

        当实体类属性和数据库的列名不一样  

实体类代码如下:
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer userId;private String userName;private Date userBirthday;private String userSex;private String userAddress;public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public Date getUserBirthday() {return userBirthday;}public void setUserBirthday(Date userBirthday) {传智播客——专注于 Java、.Net 和 Php、网页平面设计工程师的培训北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090this.userBirthday = userBirthday;}public String getUserSex() {return userSex;}public void setUserSex(String userSex) {this.userSex = userSex;}public String getUserAddress() {return userAddress;}public void setUserAddress(String userAddress) {this.userAddress = userAddress;}@Overridepublic String toString() {return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="+ userBirthday + ", userSex="+ userSex + ", userAddress=" + userAddress + "]";}}
2 Dao
接口
/*** 查询所有用户* @return*/List
findAll();
3
映射配置
4
测试查询结果
@Testpublic void testFindAll() {List
users = userDao.findAll();for(User user : users) {System.out.println(user);}}

因为
mysql
windows
系统中不区分大小写,所以userName可以查询到
5
修改映射配置
使用别名查询

          resultMap 结果类型

1
定义
resultMap
id
标签:用于指定主键字段
result
标签:用于指定非主键字段
column
属性:用于指定数据库列名
property
属性:用于指定实体类属性名称
2
映射配置
3
测试结果
@Testpublic void testFindAll() {List
users = userDao.findAll();for(User user : users) {System.out.println(user);}}

  MyBatis中Dao层开发

          MyBatis传统开发
1
持久层
Dao
接口
/**** 

Title: IUserDao

*

Description: 用户的业务层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 查询所有用户* @return*/List
findAll();/*** 根据 id 查询* @param userId* @return*/User findById(Integer userId);/*** 保存用户* @param user* @return 影响数据库记录的行数*/int saveUser(User user);/*** 更新用户* @param user* @return 影响数据库记录的行数*/int updateUser(User user);/*** 根据 id 删除用户* @param userId* @return*/int deleteUser(Integer userId);/*** 查询总记录条数* @return*/int findTotal();}
2
持久层
Dao
实现类
/**** 

Title: UserDaoImpl

*

Description: dao 的实现类

*

Company: http://www.itheima.com/

*/public class UserDaoImpl implements IUserDao {private SqlSessionFactory factory;public UserDaoImpl(SqlSessionFactory factory) {this.factory = factory;}@Overridepublic List
findAll() {SqlSession session = factory.openSession();List
users = session.selectList("com.itheima.dao.IUserDao.findAll");session.close();return users;}@Overridepublic User findById(Integer userId) {SqlSession session = factory.openSession();User user = session.selectOne("com.itheima.dao.IUserDao.findById",userId);session.close();return user;}@Overridepublic int saveUser(User user) {SqlSession session = factory.openSession();int res = session.insert("com.itheima.dao.IUserDao.saveUser",user);session.commit();session.close();return res;}@Overridepublic int updateUser(User user) {SqlSession session = factory.openSession();int res = session.update("com.itheima.dao.IUserDao.updateUser",user);session.commit();session.close();return res;}@Overridepublic int deleteUser(Integer userId) {SqlSession session = factory.openSession();int res = session.delete("com.itheima.dao.IUserDao.deleteUser",userId);session.commit();session.close();return res;}@Overridepublic int findTotal() {SqlSession session = factory.openSession();int res = session.selectOne("com.itheima.dao.IUserDao.findTotal");session.close();return res;}}
3
持久层映射配置
select * from user where id = #{uid}
select last_insert_id();
insert into user(username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})
update user setusername=#{username},birthday=#{birthday},sex=#{sex},address=#{address} whereid=#{id}
delete from user where id = #{uid}
4
测试类
/**** 

Title: MybastisCRUDTest

*

Description: 测试 mybatis 的 crud 操作

*

Company: http://www.itheima.com/

*/public class MybastisCRUDTest {private InputStream in ;private SqlSessionFactory factory;private IUserDao userDao;@Testpublic void testFindAll() {List
users = userDao.findAll();for(User user : users) {System.out.println(user);}}@Testpublic void testFindOne() {//6.执行操作User user = userDao.findById(56);System.out.println(user);}@Testpublic void testSaveUser() throws Exception {User user = new User();user.setUsername("mybatis dao user");//6.执行操作int res = userDao.saveUser(user);System.out.println(res);System.out.println(user.getId());}@Testpublic void testUpdateUser()throws Exception{//1.根据 id 查询User user = userDao.findById(41);//2.更新操作user.setAddress("北京市顺义区");int res = userDao.updateUser(user);System.out.println(res);}@Testpublic void testDeleteUser() throws Exception {//6.执行操作int res = userDao.deleteUser(56);System.out.println(res);}@Testpublic void testFindTotal() throws Exception {//6.执行操作int res = userDao.findTotal();System.out.println(res);}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 Dao 接口的实现类userDao = new UserDaoImpl(factory);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{//7.释放资源in.close();}}

编写Dao实现类的执行过程

——————————————————————————————————————————————————————————————————————————————————————————————————————

 

 

代理Dao的执行过程

SqlMapConfig.xml配置文件

1 SqlMapConfig.xml
中配置的内容和顺序
-properties
(属性)
--property
-settings
(全局配置参数)
--setting
-typeAliases
(类型别名)
--typeAliase
--package
-typeHandlers
(类型处理器)
-objectFactory
(对象工厂)
-plugins
(插件)
-environments
(环境集合属性对象)
--environment
(环境子属性对象)
---transactionManager
(事务管理)
---dataSource
(数据源)
-mappers
(映射器)
--mapper
--package

       2 properties(属性)

在使用
properties
标签配置时,我们可以采用两种方式指定属性配置。
第一种
传智播客——专注于 Java、.Net 和 Php、网页平面设计工程师的培训北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
第二种
1 在
classpath
下定义
db.properties
文件
jdbc.driver
=
com.mysql.jdbc.Driver
jdbc.url
=
jdbc:mysql://localhost:3306/eesy
jdbc.username
=
root
jdbc.password
=
1234
2 properties
标签配置
3
此时我们的
dataSource
标签就变成了引用上面的配置

       3 typeAliases(类型别名)

在前面我们讲的
Mybatis
支持的默认别名,我们也可以采用自定义别名方式来开发。
1
自定义别名:
SqlMapConfig.xml
中配置:

       4 mappers(映射器)

1 <mapper resource=" " />
使用相对于类路径的资源
如:
<mapper resource="com/itheima/dao/IUserDao.xml" />
2 <mapper class=" " />
使用
mapper
接口类路径
如:<mapper class="com.itheima.dao.UserDao"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中
3 <package name=""/>
当指定了之后就不需要再写mapper以及resource或者class了
注册指定包下的所有
mapper
接口
如:
<package name="cn.itcast.mybatis.mapper"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中

 

 

 

 

转载地址:https://blog.csdn.net/m0_56426304/article/details/117700023 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:MyBatis(三)
下一篇:Mybatis(一)

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月23日 08时14分05秒