文章目录
- 第1章 SSM的学习路线
- 第2章 Mabatis阶段介绍
- 第3章 Mybatis的概述
- 第4章 Mybatis框架入门
- 4.1 创建Maven工程并引入相关坐标
- 4.2 导入Maven依赖
- 4.3 创建数据库
- 4.4创建实体类
- 4.5 创建接口UserDao.java
- 4.6 创建sqlMapConfig.xml
- 4.7 创建UserDao.xml
- 4.8 创建测试类
- 4.9 使用注解代替UserDao.xml
- 第5章 Mabatis的CRUD(操作接口)(掌握)
- 第6章 Mybatis的参数深入
- 第7章 Mybatis实现DAO接口的实现类开发(了解)
第1章 SSM的学习路线
第一部分:mybatis(3阶段)
第二部分:spring(4阶段)
第三部分:springmvc(3阶段)
第2章 Mabatis阶段介绍
第一阶段:mybatis的入门+mybatis的基本操作
mybatis环境搭建(xml)
* 操作数据库CRUD的实现
* mybaits中的参数和结果集封装
* 分析mybatis中两种dao的编写方式
* 面向接口(推荐)
* 使用API面向实现类(不推荐)
第二阶段:mybatis深入
连接池的深入
动态sql语句的深入
表关系的深入(一对多,多对多) 特殊:多对一/一对一
第三阶段:mybatis中的加载策略和缓存以及基于注解的mybatis开发
加载策略(立即加载/延迟加载)
缓存(一级缓存/二级缓存)
注解开发Mybatis
本阶段目标
1:能够了解什么是框架(第3章)
2:掌握Mybatis框架开发快速入门(第4章)
3:掌握Mybatis框架的基本CRUD操作(代理)(第5章)
4:掌握Mybatis的参数深入(第6章)
5:掌握Mybatis的DAO层实现类开发(了解)(第7章)
第3章 Mybatis的概述
3.1 什么是Mybatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.2 ,其发布时间是2019年7月15日。
Mybatis(Hibernate)就是一个持久层的的框架。对JDBC做了轻量级封装。
3.2 什么是框架
3.2.1 什么是框架
JavaEE开发是分层的:表现层 业务层 持久层
常见的JavaEE 开发框架
1)解决数据的持久化问题的框架
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
作为持久层的框架,还有一个封装程度更高的框架就是 Hibernate,但这个框架因为各种原因目前在国内的流行程度下降太多,现在公司开发也越来越少使用。 目前使用 Spring Data 来实现数据持久化也是一种趋势
2)解决 WEB层问题的 MVC 框架
**Spring MVC**属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。
Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。
3)解决技术整合问题的框架
**Spring**是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full**-stack**(一站式) 轻量级开源框架。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB
范围:任何Java应用
Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。
3.2.2 mybatis框架
明确:它是一个持久层框架,解决项目对数据库的CRUD操作,只要会方法名、sql语句,学mybatis框架很轻松。
3.2.3 持久层技术
回顾JDBC操作数据库
代码和缺点:见另外一篇博客 JDBC操作数据库
3.2.4 mybatis概述
它是基于Java编写的持久层框架,使开发者不必关心传统jdbc的api,只关心sql语句本身。
mybatis 通过 xml或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。
什么是ORM?
ORM :Object Relational Mapping 对象关系映射(目的:操作对象,就可以操作数据库)
通过建立数据库表和Java实体类的对应关系,从而实现操作实体类就相当于操作数据库表。
ORM思想对应的框架有:mybatis(半自动),hibernate(全自动),spring data jpa(全自动,底层封装的就是hibernate)
现阶段的数据访问层框架:
第4章 Mybatis框架入门
4.1 创建Maven工程并引入相关坐标
创建项目mybaits_day01_quick
1.检查JDK环境
2.检查Tomcat环境(忽略,springmvc用到)
3.检查maven环境
4.2 导入Maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>mybatis_day01_quick</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<!-- 日志坐标 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
4.3 创建数据库
创建数据库
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性别',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
导入数据
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'小猪佩琪','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');
4.4创建实体类
创建包:cn.iyhome.domain创建类:User.java
public class User implements Serializable {
private int id;// 主键ID
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", address='" + address + '\'' +
'}';
}
}
4.5 创建接口UserDao.java
创建接口,UserDao.java,用来操作数据库
创建包cn.iyhome.dao,创建接口IUserDao.java
public interface IUserDao {
/**
* 查询所有
*/
List<User> findAll();
}
也有人将它命名UserMapper,这个是因人而异,我们为了大家的编程习惯,叫做Dao。
4.6 创建sqlMapConfig.xml
在resources包下,新建sqlMapConfig.xml,表示mybatis的配置文件
为了更好将数据库连接信息抽取出来,我们原来在C3P0连接池中也已经将数据库连接信息抽取出来,我们现在也一样将数据库的连接信息抽取出来,放到一个xml(SqlMapConfig.xml)文件中,后面再去对此配置文件进行xml解析,这样就可以将配置文件中的信息读取出来,以便在jdbc代码中直接使用这些数据库连接信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置mybatis环境-->
<environments default="mysql">
<environment id="mysql">
<!--配置事务管理-->
<transactionManager type="JDBC"/>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisblog"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件信息-->
<mappers>
<mapper resource="cn/iyhome/dao/IUerDao.xml"/>
</mappers>
</configuration>
4.7 创建UserDao.xml
因为是maven项目,所有xml的文件应该放在resources下,创建包com.itheima.dao,创建UserDao.xml,表示mybatis的映射文件(Dao有几个,映射文件就有几个)
<?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">
<mapper namespace="com.iyhome.dao.IUserDao">
<!--查找所有-->
<select id="findAll" resultType="cn.iyhome.domain.User">
select * from user
</select>
</mapper>
4.8 创建测试类
在test文件夹下,创建包con.iyhome.test,创建类MyBatisTest.java
public class MyBatisTest {
/**
* 测试mybatis的环境搭建
*/
public static void main(String[] args) throws IOException {
//读取配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//构建SqlSessionFactory
SqlSessionFactoryBuilder ssFacBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory ssFac = ssFacBuilder.build(is);
//使用工程创建SqlSession
SqlSession sqlSession = ssFac.openSession();
//使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//执行Dao的findAll方法
List<User> users = userDao.findAll();
//遍历
for (User user : users) {
System.out.println(user);
}
//关闭资源
sqlSession.close();
is.close();
}
}
查看测试结果
4.9 使用注解代替UserDao.xml
需要修改两个地方:
1.SqlMapConfig.xml
2.IUserDao.java
<!--配置映射文件信息-->
<mappers>
<!--<mapper resource="cn/iyhome/dao/IUerDao.xml"/>-->
<!--如果是使用注解的话,此处应该是用class属性指定被注解的dao全限定类名-->
<mapper class="cn.iyhome.dao.IUserDao"/>
</mappers>
public interface IUserDao {
/**
* 查询所有
*/
@Select("select * from user")
List<User> findAll();
}
测试结果
总结:Mybatis操作数据库对比往常,无非多了两个配置文件以及使用代理执行Dao中方法.
SqlMapConfig.xml ->配置mybatis环境,事务管理,数据源,配置映射文件信息(IUserDao.xml)
IUserDao.xml ->映射对应的Dao接口和方法,要执行的sql语句,返回的结果集
test.java ->使用SqlSessionFactory构建SqlSession对象,再构建代理对象执行操作数据库的方法
第5章 Mabatis的CRUD(操作接口)(掌握)
需求:实现查询所有的用户操作
5.1 查询所有
已经完成(略)
5.2 保存
需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
3.添加日志log4j(非必须),此处添加是为了显示save()操作出现的问题
先恢复SqlMapConfig.xml代码,使用xml配置文件的方式,注解的方法后面再讲
<!--配置映射文件信息-->
<mappers>
<mapper resource="cn/iyhome/dao/IUerDao.xml"/>
<!--如果是使用注解的话,此处应该是用class属性指定被注解的dao全限定类名-->
<!--<mapper class="cn.iyhome.dao.IUserDao"/>-->
</mappers>
在IUserDao.java中添加方法
/**
* 保存用户
*/
void saveUser(User user);
修改IUserDao.xml
<mapper namespace="cn.iyhome.dao.IUserDao">
<!--查找所有-->
<select id="findAll" resultType="cn.iyhome.domain.User">
select * from user
</select>
<!--保存用户-->
<insert id="saveUser" parameterType="cn.iyhome.domain.User">
insert into user values(${username},${birthday},${sex},${address})
</insert>
</mapper>
我们可以发现,这个sql语句中使用#{}字符,#{}代表占位符,我们可以理解是原来jdbc所学的?,它们都是代表占位符, 具体的值是由User类的username属性来决定的。使用OGNL表达式
parameterType属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
注意:
这种方式要求,同时还要求 select,insert,delete,update这些标签中的id属性一定与代理接口中的方法名相同。
编写测试类
为了不写重复代码,我们先将测试类中的部分代码提取到方法中,然后编写测试方法
public class MybatisTest {
InputStream is;
SqlSessionFactoryBuilder ssFacBuilder;
SqlSessionFactory ssFac;
SqlSession sqlSession;
@Before
public void init() throws IOException {
//读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//构建SqlSessionFactory
ssFacBuilder = new SqlSessionFactoryBuilder();
ssFac = ssFacBuilder.build(is);
//使用工程创建SqlSession
sqlSession = ssFac.openSession();
}
@After
public void release() {
//关闭资源
sqlSession.close();
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
//使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//执行Dao的findAll方法
List<User> users = userDao.findAll();
//遍历
for (User user : users) {
System.out.println(user);
}
}
@Test
public void saveUser() {
User user = new User();
user.setAddress("中国西安");
user.setUsername("海哥");
user.setBirthday(new Date());
user.setSex("男");
//使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
userDao.saveUser(user);
}
}
运行测试类,控制台没有报错,但是查询数据库user表,并没有插入新数据,这是为什么?
我们来添加log4j日志文件查看原因
a.在pom.xml中添加坐标
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
ps:坐标是否添加成功,可以看此处
b.在resources文件下创建log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
再次运行测试类,观察控制台输出,操作被回滚了. 解决方案:手动提交事务,在测试类中提交事务
@After
public void release() {
//提交事务
sqlSession.commit();
//关闭资源
sqlSession.close();
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
再次运行测试类,可以再控制台看到事务已经提交了,并且在数据库中查看数据也已经插入成功了.
但其实还是有一个小问题,我们来看.
修改测试代码,然后运行测试类
@Test
public void saveUser() {
User user = new User();
user.setAddress("中国西安");
user.setUsername("海哥");
user.setBirthday(new Date());
user.setSex("男");
System.out.println("保存操作之前:"+user);
//使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
userDao.saveUser(user);
System.out.println("保存操作之后:"+user);
}
看控制台的输出,这时候发现保存操作之前User对象的id和保存操作之后User对象的id都为null,如果我们想在保存之后获取User对象的id呢?
问题扩展:新增用户id的返回值
新增用户后,同时还要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长auto_increment的值返回。
Mysql自增主键的返回,语句如下:
insert into user(username,address,sex,birthday) values('张三','深圳','女','2018-07-24');
select last_insert_id()
修改IUserDao.xml
<!--保存用户-->
<insert id="saveUser" parameterType="cn.iyhome.domain.User">
<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>
查看
5.3 修改用户信息
需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
修改IUserDao.java
/**
* 修改用户信息
*/
void updateUser(User user);
修改IUserDao.xml
<!--修改用户-->
<update id="updateUser" parameterType="cn.iyhome.domain.User">
update user set sex=#{sex} where id=#{id}
</update>
编写测试类
@Test
public void updateUser() {
User user = new User();
user.setSex("女");
user.setId(55);
//使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
userDao.updateUser(user);
}
查看结果
5.4 删除用户
需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
修改IUserDao.java
/**
* 删除用户
*/
void deleteUser(Integer id);
修改IUserDao.xml
<!--删除用户-->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
其中的#{uid}是占位符,代表参数的值由方法的参数传入进来的。
注意:
1.此处的#{uid}中的id其实只是一个形参,所以它的名称是*定义的,比如定义成#{abc}也是可以的。
2.关于parameterType的取值问题,对于基本类型我们可以直接写成int,short,double……也可以写成java.lang.Integer。
3.字符串可以写成string,也可以写成java.lang.String
也就是说:int是java.lang.Integer的别名
string是java.lang.String的别名
别名是不区分大小写
编写测试类
@Test
public void deleteUser() {
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
userDao.deleteUser(42);
}
查看结果:
5.5 主键查询
需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
修改IUserDao.java
/**
* 根据id查询用户信息
* @param id
* @return
*/
User findById(Integer id);
修改IUserDao.xml
<!-- 根据id查询用户 -->
<select id="findById" parameterType="INT" resultType="cn.iyhome.domain.User">
select * from user where id = #{uid}
</select>
编写测试类
/**
* 测试主键ID查询操作
*/
@Test
public void testFindOne(){
//5.执行查询一个方法
User user = userDao.findById(50);
System.out.println(user);
}
5.6 模糊查询
需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
修改IUserDao.java
/**
* 根据名称模糊查询用户信息
* @param name
* @return
*/
List<User> findByName(String name);
修改IUserDao.xml
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
select * from user where username like #{name}
</select>
编写测试类
/**
* 测试主键ID查询操作
*/
@Test
@Test
public void testFindByName(){
//5.执行查询一个方法
List<User> users = userDao.findByName("%王%");
for(User user : users){
System.out.println(user);
}
}
问题扩展 模糊查询的另一种配置方式
修改IUserDao.xml中的sql语句:
select * from user where username like '%${value}%'
注:我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。
修改测试方法:
@Test
public void testFindByName(){
//5.执行查询一个方法
//List<User> users = userDao.findByName("%王%");
List<User> users = userDao.findByName("王");
for(User user : users){
System.out.println(user);
}
}
#{}和${}的区别
- #{}表示一个占位符号
通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
- ${}表示拼接sql串
通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
那么为什么一定要写成${value}呢?我们一起来看TextSqlNode类的源码:
这就说明了源码中指定了读取的key的名字就是”value”,所以我们在绑定参数时就只能叫value的名字了。
第6章 Mybatis的参数深入
1:Mybatis的映射文件其实就是与DAO相对应,因为DAO中的方法有输入参数及返回结果,那么在Mybatis的映射文件中自然也就有与之对应的参数和返回结果。
2:在Mybatis的映射文件中参数用parameterType来代表,它的值可以是基本类型,也可以是包装的对象,这一点我们第二天学习中就使用过。
3:在Mybatis的映射文件中返回结果用resultType或resultMap来代表。
resultType:当查询字段和封装实体的属性名称一致的情况下
resultMap:当查询字段和封装实体的属性名称不一致的情况下
6.1 了解OGNL
OGNL表达式:
Object Graphic Navigation Language
对象 图 导航 语言
它是通过对象的取值方法来获取数据。在写法上把get给省略了。
比如:我们获取用户的名称
-
类中的写法:user.getUsername();
-
OGNL表达式写法:user.username
mybatis中为什么能直接写username,而不用user.呢:
- 因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo(Plain Ordinary Java Object)属性名称。
6.2 Mybatis的参数
6.2.1 parameterType(输入类型)
-
传递简单类型 (略)
int – int 或者 java.lang.Integer
String – string 或者java.lang.String
…别名不区分大小写。
-
传递pojo对象
com.itheima.domain.User-- username、address、sex、birthday、id
6.2.2 QueryVo.java
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
需要涉及添加代码的文件
1.添加QueryVO.java
2.IUserDao.java
3.IUserDao.xml
添加QueryVo.java
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
修改IUserDao.java
/**
* 查询用户信息byQueryVo
*/
void findUserByQueryVO();
修改IUserDao.xml
<!--查找用户byQueryVo-->
<select id="findUserByQueryVO" parameterType="cn.iyhome.domain.QueryVo" resultType="cn.iyhome.domain.User">
select * from user where username=#{user.username}
</select>
如果我们使用的是包装类作为参数,比如这个示例的QueryVo类作为findUserByVo()方法的参数,那么在使用时,因为QueryVo类中有一个User类的user对象,而这个user对象中才能找到username属性,所以我们在访问属性时,就使用OGNL表达式才访问对象的属性,即#{user.username}。
编写测试类:
@Test
public void selectUser() {
User user = new User();
user.setUsername("海哥");
QueryVo qv = new QueryVo();
qv.setUser(user);
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
List<User> list = userDao.findUserByQueryVO(qv);
for (User users : list) {
System.out.println(users);
}
}
6.3 Mybatis的输出结果封装
6.3.1 resultType(输出类型) 输出简单类型
看下边的例子输出整型:
IUserDao.xml文件
<!-- 获取用户的总记录条数 -->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
IUserDao.java
/**
*查询用户数
*/
void findTotal();
测试类文件
/**
* 测试查询总记录条数
*/
@Test
public void testFindTotal(){
//5.执行查询一个方法
int count = userDao.findTotal();
System.out.println(count);
}
6.3.2 resultType(输出类型) 简单对象的数据类型
(1)让数据库的字段和实体类的属性一致:
参考上述[查找所有用户的案例]点击跳转
(2)数据库中的字段和对象中的属性不一致:
修改iy.home.domain.User.java
public class User implements Serializable {
private int id;
//username- > name
private String name;
//sex -> gender
private String gender;
private Date birthday;
private String address;
//getter
//setter
@Override
public String toString() {
//...
}
}
在不一致的情况下,如果不改动IUserDao.xml文件,那么不一致的字段查询到的值为null值.
所以需要我们做一个手动匹配.方案有两种
方案一
通过改别名的方式 , 修改UserDao.xml
<!--查找所有-->
<select id="findAll" resultType="cn.iyhome.domain.User">
/*select * from user*/
select id,username as name,sex as gender ,birthday,address from user
</select>
查询结果:
方案二(推荐)
使用resultMap,修改UserDao.xml
<!--查找所有-->
<select id="findAll" resultMap="userMap">
select * from user
/*select id,username as name,sex as gender ,birthday,address from user*/
</select>
<resultMap id="userMap" type="cn.iyhome.domain.User">
<!--id表示主键对应的字段-->
<id property="id" column="id"/>
<!--result表示非主键的字段-->
<result property="name" column="username"/>
<result property="gender" column="sex"/>
<!--属性名和列名一致的可以省略,如birthday/address-->
</resultMap>
<id/>:此属性表示查询结果集的唯一标识。如果是多个字段为复合唯一约束则定义多个<id/>。
property:表示User类的属性。
column:表示sql查询出来的字段名。
column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
<result />:普通属性(普通字段),即pojo的属性。
property:表示User类的属性。
column:表示sql查询出来的字段名。
column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
查询结果:
第7章 Mybatis实现DAO接口的实现类开发(了解)
使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方式(定义实现Dao接口的实现类)和Mapper接口代理开发方式(通用)。而现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便,上述6章我们使用的就是代理方式。
以查找所有用户为例
1.创建工程mybatis_dao_impl
略(/滑稽)
2.导入maven的坐标
需要带入的有: Junit ,mybatis,mysql-connector-java,log4j(自选)
3.编写java类,资源文件,测试类
需要编写的有:
java类:
cn.iyhome.daomain.User.java
cn.iyhome.dao.IUerDao.java
cn.iyhome.dao.impl.IUserDaoImpl.java
资源文件
resources/cn/iyhome/dao/IUserDao.xml
resources/SqlMapConfig.xml
resources/log4j.properties(自选)
测试类:
test.java.cn.iyhome.test.MybatisTest.java
IUserDaoImpl.java实现类代码
public class IUserDaoImpl implements IUserDao {
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.factory = sqlSessionFactory;
}
public List<User> findAll() {
// 根据SqlSessionFactory获取SqlSession对象
SqlSession sqlSession = factory.openSession();
// 调用SqlSession中的方法,实现查询列表
// 参数就是能获取匹配信息的key(namespace+"."+id)
List<User> list = sqlSession.selectList("cn.iyhome.dao.IUserDao.findAll");
// 释放资源
sqlSession.close();
return list;
}
}
测试类MybatisTest.java代码
public class MybatisTest {
private InputStream in;
private UserDao userDao;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取dao的实现类对象
userDao = new UserDaoImpl(factory);
}
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
in.close();
}
/**
* 测试查询所有
*/
@Test
public void testFindAll(){
//4.执行查询所有方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
}
}
其他的增删改查操作类似,不做阐述
在本阶段,只是入门案例,其实还存在很多问题.比如:
1.数据源的配置是否可以抽取
2.SqlMapConfig.xml文件中各种全限定类名很繁琐,是否可以简写
3.如果是动态的sql语句又需要如果编写
4.Mybatis的多表查询又是如何处理的