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操作的更多相关文章

  1. SSM框架之Mybatis(7)延迟加载、缓存及注解

    Mybatis(7)延迟加载.缓存及注解 1.延迟加载 延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据.延迟加载也称懒加载. **好处:**先从单表查询,需要时再从关联表去关 ...

  2. 【MyBatis】MyBatis实现CRUD操作

    1.实现基本CRUD功能 使用MyBatis对数据完整的操作,也就是CRUD功能的实现.根据之前的内容,要想实现CRUD,只需要进行映射文件的配置. 范例:修改EmpMapper.xml文件,实现CR ...

  3. SSM框架之Mybatis(3)dao层开发

    Mybatis(3)dao层开发 以实现类完成CRUD操作 1.持久层dao层接口的书写 src\main\java\dao\IUserDao.java package dao; import dom ...

  4. 05 Mybatis的CRUD操作和Mybatis连接池

    1.CRUD的含义 CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写.主要被用在描述软件系统中 ...

  5. ssm框架的搭建实现CRUD的操作

    最近在开发公司的一个系统,系统的框架是用ssm的框架搭建的,当然和这次写博客的不一样,它拥有很多的配置文件,企业级的开发所需要的配置文件是非常繁琐的,今天记录一下一个简单的SSM框架的搭建和实现一个C ...

  6. SSM框架-初学Mybatis框架

    SSM(Spring+SpringMVC+Mybatis)是目前项目开发比较流行的一套组合框架,而Mybatis是负责数据库操作的那部分框架,具体 我也说不上来 传统的JDBC操作比较冗长而繁琐,而用 ...

  7. SSM框架之MyBatis框架实现简单的增删改查

    MyBatis框架介绍 MyBatis是一个优秀的数据持久层框架,在实体类和SQL语句之间建立映射关系是一种半自动化的ORM实现,其封装性要低于Hibernate,性能优越,并且小巧,简单易学,应用也 ...

  8. SSM框架-使用MyBatis Generator自动创建代码

    参考:http://blog.csdn.net/zhshulin/article/details/23912615 SSM搭建的时候用到MyBatis的代码自动生成的功能,由于MyBatis属于一种半 ...

  9. Java框架-mybatis02基本的crud操作

    1.搭建mybatis框架 1)导入相关jar包 2)编写核心配置文件(配置数据库连接的相关信息以及配置mapper映射文件) 3)编写dao操作 4)编写mapper映射文件 5)编写实体类 2.执 ...

随机推荐

  1. node http 模块 常用知识点记录

    关于 node,总是断断续续的学一点,也只能在本地自己模拟实战,相信总会有实战的一天~~ http 作为服务端,开启服务,处理路由,响应等 http 作为客户端,发送请求 http.https.htt ...

  2. Flask 教程 第七章:错误处理

    本文翻译自The Flask Mega-Tutorial Part VII: Error Handling 这是Flask Mega-Tutorial系列的第七部分,我将告诉你如何在Flask应用中进 ...

  3. Servlet 使用介绍(3)

    说明 本篇记录一个Servlet的创建过程和基本使用.由于,Servlet是基于Http协议使用的,所以,可以在http协议的基础上作一些改变,来修改适用我自己的servlet. Servlet使用 ...

  4. MYSQL的基本使用,以及错误代码的意思

    创建数据库: 要创建声明类型的数据库,输入CREATE DATABASE 数据库名称; 注意:命令不必以大写字母输入. 注意:所有MySQL命令必须以";"结束.如果忘记了输入分号 ...

  5. June 03rd, 2019. Week 23rd, Monday

    There is no shame in hard work. 努力从来不丢人. Stop complaining about the current work arrangements, just ...

  6. React 以两种形式去创建组件 类或者函数(二)

    08==>创建组件以 1类的形式 或者以 2函数的形式 09==>使用组件 在src下创建components文件夹 是放组件的 CompType.js 组件 组件开头大写(重要) Com ...

  7. 我的第一个Mybatis项目搭建

    1.新建maven项目,目录如下.第一个坑idea目录和eclipse不一样project就像workspace pom文件 jdk版本有点高建议8.0 <?xml version=" ...

  8. poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...

  9. 算法问题实战策略 NTHLON

    地址 https://algospot.com/judge/problem/read/NTHLON #include <iostream> #include <vector> ...

  10. 开发工具IntelliJ IDEA

    开发工具概述 IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量.它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中, ...