SSM框架之Mybatis(2)CRUD操作
Mybatis(2)CRUD
1、基于代理Dao实现CRUD操作
使用要求:
1、持久层接口(src\main\java\dao\IUserDao.java)和持久层接口的映射配置(src\main\resources\dao\IUserDao.xml)必须在相同的包下
2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
<mapper namespace="dao.IUserDao">
3、SQL 语句的配置标签,,,的 id 属性必须和持久层接口的
方法名相同。
持久层接口的方法
/**
* 查询所有数据
* @return
*/
List<User> findAll();
SQL 语句的配置标签id 属性
<select id="findAll" resultType="domain.User">
select * from user
</select>
关于测试类的一些细节:
package test;
import bao;//此处是要导入的包,为了节约空间所以省略
public class MybatisTest {
/**
* 测试mybatis的CRUD操作
*/
//全局属性用于实现对应操作
InputStream in;
SqlSession sqlSession;
IUserDao uesrdao;
//before注释说明该方法最先执行相当于servlet中的init方法
//用于给对应对象赋值用于后续的增删改查操作
//这几个对象是通用的所以提出来
//也可以写工具类来实现
@Before
public void init() throws Exception {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
sqlSession = build.openSession();
uesrdao = sqlSession.getMapper(IUserDao.class);
}
//before注释说明该方法最后执行相当于servlet中的destory方法
//用于释放资源
@After
public void destory() throws Exception {
sqlSession.commit();
sqlSession.close();
in.close();
}
1.1、据根据 ID查询
1.1.1、在持久层接口中添加 findById
/**
* 根据id查询用户
* @param id
*/
User findById(int id);
1.1.2、在用户的映射配置文件中配置
<select id="findById" parameterType="int" resultType="domain.User">
select * from user where id=#{id}
</select>
细节:
resultType 属性:用于指定结果集的类型。
parameterType :用于指定传入参数的类型。
sql 语句中使用#{} 字符 :它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
具体的数据是由#{}里面的内容决定的。
.#{} 中内容的写法:由于数据类型是基本类型,所以此处可以随意写。
1.1.3、在测试类添加测试
@Test
public void testFindOne(){
//通过id查找用户
User user = uesrdao.findById(48);
System.out.println(user);
}
1.2、添加操作
1.2.1、在持久层接口中添加 addUser
/**
* 添加用户
* @param user
*/
void addUser(User user);
1.2.2、在用户的映射配置文件中配置
<insert id="addUser" parameterType="domain.User">
insert into user (username,address,sex,birthday) value (#{username},#{address},
#{sex},#{birthday})
</insert>
1.2.3、在测试类添加测试
@Test
public void testAddUser(){
//添加用户
User user = new User();
user.setUsername("wf");
user.setAddress("中国");
user.setSex("男");
user.setBirthday(new Date());
//执行添加操作
uesrdao.addUser(user);
}
1.3、删除操作
1.3.1、在持久层接口中添加 deleteUser
/**
* 添加用户
* @param user
*/
void addUser(User user);
1.3.2、在用户的映射配置文件中配置
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
1.3.3、在测试类添加测试
@Test
public void testDeleteUser(){
//删除用户
uesrdao.deleteUser(49);
}
1.4、更新操作
1.4.1、在持久层接口中添加 updateUser
/**
* 更新用户
* @param user
*/
void updateUser(User user);
1.4.2、在用户的映射配置文件中配置
<update id="updateUser" parameterType="domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday}
</update>
1.4.3、在测试类添加测试
@Test
public void testDeleteUser(){
//删除用户
uesrdao.deleteUser(49);
}
1.5、用户模糊查询
1.5.1、在持久层接口中添加 findByName
/**
* 模糊查询用户信息
* @return
*/
List<User> findByName(String str);
1.5.2、在用户的映射配置文件中配置
<select id="findByName" resultType="domain.User" parameterType="String">
<!--select * from user where username like '%${value}%'-->
<!-- 使用上面方式模糊查询时Statment对象通过字符串拼接的方式连接sql语句
下面的sql语句使用PrepatedStatement的参数占位符有预处理,
所以下面这种方式使用的多
-->
select * from user where username like #{str}
</select>
1.5.3、在测试类添加测试
@Test
public void testAddUser(){
//添加用户
User user = new User();
user.setUsername("wf");
user.setAddress("中国");
user.setSex("男");
user.setBirthday(new Date());
//执行添加操作
uesrdao.addUser(user);
}
在控制台输出的执行 SQL 语句如下:
Preparing: select * from user where username like ?
我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标
识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。
1.5.4、模糊查询的另一种配置方式
第一步:修改 SQL 语句的配置,配置如下:
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
select * from user where username like '%${value}%'
</select>
我们在上面将原来的#{}占位符,改成了value。注意如果用模糊查询的这种写法,那么{value}。注意如果用模糊查询的这种写法,那么value。注意如果用模糊查询的这种写法,那么{value}的写法就是固定的,不能写成其它名字。
第二步:测试
/**
* 测试模糊查询操作
*/
@Test
public void testFindByName(){
//5.执行查询一个方法
List<User> users = userDao.findByName("王");
for(User user : users){
System.out.println(user);
}
}
在控制台输出的执行 SQL 语句如下:
Preparing: select * from user where username like ‘%王% ’
可以发现,我们在程序代码中就不需要加入模糊查询的匹配符%了,这两种方式的实现效果是一样的,但执行
的语句是不一样的。
1.5.5、模糊查询的${value}
我们一起来看 TextSqlNode 类的源码:
public String handleToken(String content) {
Object parameter = this.context.getBindings().get("_parameter");
if (parameter == null) {
this.context.getBindings().put("value", (Object)null);
} else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
this.context.getBindings().put("value", parameter);
}
Object value = OgnlCache.getValue(content, this.context.getBindings());
String srtValue = value == null ? "" : String.valueOf(value);
this.checkInjection(srtValue);
return srtValue;
}
这就说明了源码中指定了读取的 key 的名字就是”value”,所以我们在绑定参数时就只能叫 value 的名字
了。
1.6、查询使用聚合函数
1.6.1、在持久层接口中添加 findTotal
/**
* 添加用户
* @param user
*/
void addUser(User user);
1.6.2、在用户的映射配置文件中配置
<!-- 查询总记录条数 -->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
1.6.3、在测试类添加测试
@Test
public void testFindTotal() throws Exception {
//6.执行操作
int res = userDao.findTotal();
System.out.println(res);
}
1.7、Mybatis 与 与 JDBC 编程的比较
1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
2.Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
3.向sql语句传参数麻烦,因为sql语句的where 条件不一定,可能多也可能少,占位符需要和参数对应。
解决:Mybatis自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的
类型。
4.对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对
象解析比较方便。
解决:Mybatis自动将 sql执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的
类型。
2、 Mybatis 的参数深入
2.1、使用说明
我们在上一节中已经介绍了 SQL 语句传参,使用标签的 parameterType 属性来设定。该属性的取值可以
是基本类型,引用类型(例如:String 类型),还可以是实体类类型(POJO 类)。同时也可以使用实体类的包装
类,本节将介绍如何使用实体类的包装类作为参数传递。
2.2、注意事项
基本类型和 String我们可以直接写类型名称 ,也可以使用包名 . 类名的方式 ,例如 :
java.lang.String。
实体类类型,目前我们只能使用全限定类名。
究其原因,是 mybaits 在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。
2.3 递传递pojo包装对象
开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查
询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo 类中包含 pojo。
需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。
2.3.1、编写QueryVo
package domain;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
2.3.2、在持久层接口中添加 findByVo
/**
* 模糊查询用户信息
* @return
*/
List<User> findByVo(QueryVo vo);
2.3.3、在用户的映射配置文件中配置
<select id="findByVo" resultType="domain.User" parameterType="domain.QueryVo">
select * from user where username like #{user.username}
</select>
1.2.3、在测试类添加测试
@Test
public void testFindByVo(){
//通过模糊查询查找用户
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%g%");
vo.setUser(user);
List<User> users = uesrdao.findByVo(vo);
for(User u:users){
System.out.println(u);
}
}
3、Mybatis 的输出结果封装
3.1 resultType
resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。
我们在前面的 CRUD 案例中已经对此属性进行过应用了。
需要注意的是,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须
使用全限定类名。例如:我们的实体类此时必须是全限定类名(今天最后一个章节会讲解如何配置实体类的别名)
同时,当是实体类名称是,还有一个要求, 实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
3.1.1 基本类型示例
3.1.1.1 Dao 接口
/**
- 查询总记录条数
- @return
*/
int findTotal();
3.1.1.2 映射配置
<!-- 查询总记录条数 -->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
3.1.2 实体类类型示例
3.1.2.1 Dao 接口
/**
* 查询所有用户
* @return
*/
List<User> findAll();
3.1.2.2 映射配置
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>
3.1.3 特殊情况示例
3.1.3.1 修改实体类
实体类代码如下:( 此时的实体类属性和数据库表的列名已经不一致了)
/**
*
* <p>Title: User</p>
* <p>Description: 用户的实体类</p>
*/
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;
}
//此处自动生成get和set及tostring方法
3.1.3.2 Dao 接口
/**
* 查询所有用户
* @return
*/
List<User> findAll();
3 .1.3.3 映射配置
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>
3.1.3.4 测试查询结果
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
}
结果:
User{userId=null, userName=‘gx’, userAddress=‘null’, userSex=‘null’, userBirthday=null}
User{userId=null, userName=‘gx’, userAddress=‘null’, userSex=‘null’, userBirthday=null}
User{userId=null, userName=‘gx’, userAddress=‘null’, userSex=‘null’, userBirthday=null}
User{userId=null, userName=‘gx’, userAddress=‘null’, userSex=‘null’, userBirthday=null}
为什么名称会有值呢?
因为:mysql 在 在 windows private String userName;
3.1.3.5 修改映射配置
使用别名查询
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select id as userId,username as userName,birthday as userBirthday,
sex as userSex,address as userAddress from user
</select>
运行结果:
User{userId=41, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=42, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=43, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=45, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
如果我们的查询很多,都使用别名的话写起来岂不是很麻烦,有没有别的解决办法呢?
3.2 resultMap
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类
型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
3.2.1 定义 resultMap
<!-- 建立 User 实体和数据库表的对应关系
type 属性:指定实体类的全限定类名
id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
-->
<resultMap type="com.itheima.domain.User" id="userMap">
<id column="id" property="userId"/>
<result column="username" property="userName"/>
<result column="sex" property="userSex"/>
<result column="address" property="userAddress"/>
<result column="birthday" property="userBirthday"/>
</resultMap>
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称
3.2.2 映射配置
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>
3.2.3 测试结果
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
}
运行结果:
User{userId=41, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=42, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=43, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
User{userId=45, userName=‘gx’, userAddress=‘中国’, userSex=‘女’, userBirthday=Mon Apr 15 21:28:56 CST 2019}
SSM框架之Mybatis(2)CRUD操作的更多相关文章
- SSM框架之Mybatis(7)延迟加载、缓存及注解
Mybatis(7)延迟加载.缓存及注解 1.延迟加载 延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据.延迟加载也称懒加载. **好处:**先从单表查询,需要时再从关联表去关 ...
- 【MyBatis】MyBatis实现CRUD操作
1.实现基本CRUD功能 使用MyBatis对数据完整的操作,也就是CRUD功能的实现.根据之前的内容,要想实现CRUD,只需要进行映射文件的配置. 范例:修改EmpMapper.xml文件,实现CR ...
- SSM框架之Mybatis(3)dao层开发
Mybatis(3)dao层开发 以实现类完成CRUD操作 1.持久层dao层接口的书写 src\main\java\dao\IUserDao.java package dao; import dom ...
- 05 Mybatis的CRUD操作和Mybatis连接池
1.CRUD的含义 CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写.主要被用在描述软件系统中 ...
- ssm框架的搭建实现CRUD的操作
最近在开发公司的一个系统,系统的框架是用ssm的框架搭建的,当然和这次写博客的不一样,它拥有很多的配置文件,企业级的开发所需要的配置文件是非常繁琐的,今天记录一下一个简单的SSM框架的搭建和实现一个C ...
- SSM框架-初学Mybatis框架
SSM(Spring+SpringMVC+Mybatis)是目前项目开发比较流行的一套组合框架,而Mybatis是负责数据库操作的那部分框架,具体 我也说不上来 传统的JDBC操作比较冗长而繁琐,而用 ...
- SSM框架之MyBatis框架实现简单的增删改查
MyBatis框架介绍 MyBatis是一个优秀的数据持久层框架,在实体类和SQL语句之间建立映射关系是一种半自动化的ORM实现,其封装性要低于Hibernate,性能优越,并且小巧,简单易学,应用也 ...
- SSM框架-使用MyBatis Generator自动创建代码
参考:http://blog.csdn.net/zhshulin/article/details/23912615 SSM搭建的时候用到MyBatis的代码自动生成的功能,由于MyBatis属于一种半 ...
- Java框架-mybatis02基本的crud操作
1.搭建mybatis框架 1)导入相关jar包 2)编写核心配置文件(配置数据库连接的相关信息以及配置mapper映射文件) 3)编写dao操作 4)编写mapper映射文件 5)编写实体类 2.执 ...
随机推荐
- SpringCloud的入门学习之概念理解、Zuul路由网关
1.Zuul路由网关是什么? 答:Zuul包含了对请求的路由和过滤两个最主要的功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进 ...
- (六十三)c#Winform自定义控件-箭头(工业)-HZHControls
官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...
- javaWeb技术第二篇之CSS、事件和案例
<!--内联式 CSS (层叠样式表) 编辑 层叠样式表(英文全称:Cascading Style Sheets) CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式 ...
- HTML 本地存储
HTML 本地存储:优于 cookies. 什么是 HTML 本地存储? 通过本地存储(Local Storage),web 应用程序能够在用户浏览器中对数据进行本地的存储. 在 HTML5 之前,应 ...
- ramfs 和 tmpfs 以及 ramdisk相关调研
最近需要使用到 ramfs 和 tmpfs 做内存文件系统,下面对这两个文件系统相关的信息,做一下总结: 参考链接: https://www.thegeekstuff.com/2008/11/over ...
- 【解决 FTP】windows访问Linux的vsftpd(FTP服务器)问题200 Switching to ASCII mode,227 Entering Passive Mode
转载:关于FTP主动模式(active mode)与被动模式(passive mode)的工作原理: 主动模式(服务器向客户端敲门,然后客户端开门)FTP:客户机与服务器之间建立连接时,客户机是大于1 ...
- Python爬虫(学习准备)
编码格式的认识: 字符:各种文字和符号的统称 字符集:多个字符的集合 字符集包括:ASCII字符集,GB2312字符集,GB18030,Unicode字符集等 1个字符ASCII编码占1个字节,用Un ...
- go语言设计模式之observer
observer.go package observer import ( "fmt" ) type Observer interface { Notify(string) } t ...
- Codeforces Round #606 (Div. 2)
传送门 A. Happy Birthday, Polycarp! 签到. Code /* * Author: heyuhhh * Created Time: 2019/12/14 19:07:57 * ...
- 冒泡排序和sort,sorted排序函数
冒泡: # 轮数 元素个数 比较次数# 1 6 5# 2 5 4# 3 4 3# 4 3 2# 5 2 1 # 列表有n个元素,则应比较n-1轮,即循环次数n-1 a=[85,7,4,89,34,2] ...