一、框架概述
1、什么是框架
(1)什么是框架
框架(Framework) 是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
- 简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。
(2)框架要解决的问题
- 框架要解决的最重要的一个问题是技术整合的问题,在J2EE的框架中,有着各种各样的技术,不同的软件企业需要从J2EE中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。
- 框架一般处在低层应用平台(如J2EE)和高层业务逻辑之间的中间层。
(3)软件开发的分层重要性
框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的MVC软件设计思想就是很好的分层思想。
- 通过分层更好的实现了各个部分的职责,在每一层将再细化出不同的框架,分别解决各层关注的问题。
(4)分层开发下的常见框架
常见的JavaEE开发框架:
- 解决数据的持久化问题的框架
- Mybatis框架
- 封装程度更高的框架Hibernate,但这个框架因为各种原因目前在国内的流行程度下降太多,现在公司开发也越来越少使用。
- 目前使用Spring Data来实现数据持久化也是一种趋势。
- 解决WEB层问题的MVC框架
- 解决技术整合问题的Spring框架
(5)MyBatis框架概述
- Mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
- Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由Mybatis框架执行sql并将结果映射为java对象并返回。
- 采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbcapi打交道,就可以完成对数据库的持久化操作。
2、JDBC编程的分析
(1)jdbc程序的回顾
下边使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作:
1 | public static void main(String[] args) { |
(2)jdbc问题分析
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
- Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
- 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记
录封装成pojo对象解析比较方便。
二、Mybatis框架快速入门
1、Mybatis框架开发的准备
官网下载Mybatis框架(如果创建JavaEE工程可以使用,一般不推荐)点击进入下载地址
创建普通maven工程,不需要选择模板,在pom文件中添加下面内容即可(包含在
<project>
标签内)(推荐采用)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<packaging>jar</packaging>
<dependencies>
<!--Mybatis的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--连接数据库的驱动,根据自己的数据库版本进行修改-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!--日志文件的jar包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--单元测试的jar包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>Mybatis开发文档 点击进入
2、创建所需要的表
sql语句:
1 | CREATE DATABASE javatest; |
3、编写User实体类
1 | package com.allen.domain; |
4、编写持久层接口UserDao
1 | package com.allen.dao; |
5、编写持久层接口的映射文件UserDao.xml
- 要求:
- 创建位置:必须和持久层接口在相同的包中。
- 名称:必须以持久层接口名称命名文件名,扩展名是.xml
1
2
3
4
5
6
7
8
9
10<?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.allen.dao.UserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.allen.domain.User">
select * from user
</select>
</mapper>
6、编写SqlMapConfig.xml配置文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
7、编写测试类
1 | package com.allen.test; |
8、小结
- 查询所有的分析
- 入门案例的分析
- 通过快速入门示例,我们发现使用mybatis是非常容易的一件事情,因为只需要编写Dao接口并且按照Mybatis要求编写两个配置文件,就可以实现功能。远比之前的jdbc方便多了。(使用注解之后,将变得更为简单,只需要编写一个Mybatis配置文件就够了。)
- 但是,这里面包含了许多细节,比如为什么会有工厂对象(SqlSessionFactory),为什么有了工厂之后还
要有构建者对象(SqlSessionFactoryBuilder),为什么UserDao.xml在创建时有位置和文件名的要求等等。 - 这些问题通过后面自己实现自定义Mybatis框架,就会有所认识。
- 注意:自定义Mybatis框架,不是让大家回去自己去写个 Mybatis,而是让能更好了了解Mybatis内部是怎么执行的,在以后的开发中能更好的使用Mybatis框架,同时对它的设计理念(设计模式)有一个认识。
9、补充(基于注解的 mybatis 使用)
(1)在持久层接口中添加注解
1 | package com.allen.dao; |
(2)修改SqlMapConfig.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
(3)注意事项
在使用基于注解的Mybatis配置时,先移除xml的映射配置(UserDao.xml)。
三、自定义Mybatis框架
1、自定义Mybatis框架的分析
(1)涉及知识点介绍
下面将使用前面所学的基础知识来构建一个属于自己的持久层框架,将会涉及到的一些知识点:工厂模式(Factory 工厂模式)、构造者模式(Builder 模式)、代理模式,反射,自定义注解,注解的反射,xml 解析,数据库元数据,元数据的反射等。
(2)分析流程
2、前期准备
(1)创建Maven工程
(2)引入相关坐标
在pom文件中添加下面内容即可(包含在<project>
标签内)
1 | <packaging>jar</packaging> |
(3)引入工具类到项目中
该工具类为解析Xml文件的工具类,了解即可
1 | package com.allen.mybatis.utils; |
(4)编写SqlMapConfig.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
- 注意:
- 此处我们直接使用的是mybatis的配置文件,但是由于我们没有使用mybatis的jar包,所以要把配置文件的约束删掉否则会报错(如果电脑能接入互联网,不删也行)*
(5)编写读取配置文件类
1 | package com.allen.mybatis.io; |
(6)编写Mapper类
1 | package com.allen.mybatis.cfg; |
(7)编写Configuration配置类
1 | package com.allen.mybatis.cfg; |
(8)编写User实体类
1 | package com.allen.domain; |
3、基于XML的自定义mybatis框架
(1)编写持久层接口和UserDao.xml
持久层接口UserDao
1
2
3
4
5
6
7
8
9
10
11
12
13package com.allen.dao;
import com.allen.domain.User;
import java.util.List;
public interface UserDao {
/**
* 查询所有
* @return
*/
List<User> findAll();
}UserDao.xml
1
2
3
4
5
6
7<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.allen.dao.UserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.allen.domain.User">
select * from user
</select>
</mapper>
(2)编写构建者类
1 | package com.allen.mybatis.sqlsession; |
(3)编写SqlSessionFactory接口和实现类
SqlSessionFactory接口
1
2
3
4
5
6
7
8
9package com.allen.mybatis.sqlsession;
public interface SqlSessionFactory {
/**
* 用户打开一个新的SqlSession对象
* @return
*/
SqlSession openSession();
}实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.allen.mybatis.sqlsession.defaults;
import com.allen.mybatis.cfg.Configuration;
import com.allen.mybatis.sqlsession.SqlSession;
import com.allen.mybatis.sqlsession.SqlSessionFactory;
/**
* SqlSessionFactory接口的实现类
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private Configuration cfg;
public DefaultSqlSessionFactory(Configuration cfg){
this.cfg = cfg;
}
/**
* 用于创建一个新的操作数据库对象
* @return
*/
@Override
public SqlSession openSession() {
return new DefaultSqlSession(cfg);
}
}
(4)编写SqlSession接口和实现类
SqlSession接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.allen.mybatis.sqlsession;
/**
* 自定义Mybatis中和数据库交互的核心类
* 它里面可以创建dao接口的代理对象
*/
public interface SqlSession {
/**
* 根据参数创建一个代理对象
* @param daoInterfaceClass dao的接口字节码
* @param <T>
* @return
*/
<T> T getMapper(Class<T> daoInterfaceClass);
/**
* 释放资源
*/
void close();
}实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package com.allen.mybatis.sqlsession.defaults;
import com.allen.mybatis.cfg.Configuration;
import com.allen.mybatis.sqlsession.SqlSession;
import com.allen.mybatis.sqlsession.proxy.MapperProxy;
import com.allen.mybatis.utils.DataSourceUtil;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
/**
* SqlSession接口的实现类
*/
public class DefaultSqlSession implements SqlSession {
private Configuration cfg;
private Connection conn;
public DefaultSqlSession(Configuration cfg){
this.cfg = cfg;
conn = DataSourceUtil.getConnection(cfg);
}
/**
* 用户创建代理对象
* @param daoInterfaceClass dao的接口字节码
* @param <T>
* @return
*/
@Override
public <T> T getMapper(Class<T> daoInterfaceClass) {
return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),conn));
}
/**
* 用于释放资源
*/
@Override
public void close() {
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
(5)编写用于创建Dao接口代理对象的类
1 | package com.allen.mybatis.sqlsession.proxy; |
(6)运行测试类
1 | package com.allen.test; |
4、基于注解方式定义Mybatis框架
(1)自定义@Select注解
1 | package com.allen.mybatis.annotation; |
(2)修改持久层接口
1 | package com.allen.dao; |
(3)修改 SqlMapConfig.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
5、自定义Mybatis的设计模式说明
(1)工厂模式(SqlSessionFactory)
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
(2)代理模式(MapperProxy)
- 代理模式分为静态和动态代理。静态代理,我们通常都很熟悉。有一个写好的代理类,实现与要代理的类的一个共同的接口,目的是为了约束也为了安全。
- 这里主要想说的是关于动态代理。我们知道静态代理若想代理多个类,实现扩展功能,那么它必须具有多个代理类分别取代理不同的实现类。这样做的后果是造成太多的代码冗余。那么我们会思考如果做,才能既满足需求,又没有太多的冗余代码呢?动态代理。
(3)构建者模式(SqlSessionFactoryBuilder)
从图中我们可以看出,创建者模式由四部分组成。
- 抽象创建者角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体创建者角色。具体创建者必须实现这个接口的两种方法:一是建造方法,比如图中的buildPart1和buildPart2方法;另一种是结果返回方法,即图中的getProduct方法。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少零件,就有多少相应的建造方法。
- 具体创建者角色:他们在应用程序中负责创建产品的实例。这个角色要完成的任务包括:
- 实现抽象创建者所声明的抽象方法,给出一步一步的完成产品创建实例的操作。
- 在创建完成后,提供产品的实例。
- 导演者角色:这个类调用具体创建者角色以创建产品对象。但是导演者并没有产品类的具体知识,真正拥有产
品类的具体知识的是具体创建者角色。 - 产品角色:产品便是建造中的复杂对象。一般说来,一个系统中会有多于一个的产品类,而且这些产品类并不
一定有共同的接口,而完全可以使不相关联的。
6、总结
四、基于代理Dao实现CRUD操作
1、Mybatis环境搭建步骤
- 第一步:创建maven工程
- 第二步:导入坐标
- 第三步:编写必要代码(实体类和持久层接口)
- 第四步:编写SqlMapConfig.xml
- 第五步:编写映射配置文件
- 第六步:编写测试类
2、根据ID查询
(1)在持久层接口中添加findById方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 根据 id 查询 --> |
细节:
- resultType属性:用于指定结果集的类型。
- parameterType属性:用于指定传入参数的类型。
- sql语句中使用#{}字符:它代表占位符,相当于原来jdbc部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
- #{}中内容的写法:由于数据类型是基本类型,所以此处可以随意写。
(3)在测试类添加测试
1 | public class MybastisCRUDTest { |
3、保存操作
(1)在持久层接口中添加新增方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 保存用户--> |
- #{}中内容的写法:
由于我们保存方法的参数是一个User对象,此处要写User对象中的属性名称。 - 它用的是 ognl 表达式。*
- ognl表达式:
- 它是apache提供的一种表达式语言*,全称是:Object Graphic Navigation Language 对象图导航语言它是按照一定的语法格式来获取数据的。语法格式就是使用
#{对象.对象}
的方式 - #{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用
getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user,而直接写username。
(3)添加测试类中的测试方法
1 | @Test |
打开Mysql数据库发现并没有添加任何记录,原因是什么?
- 这一点和jdbc是一样的,我们在实现增删改时一定要去控制事务的提交,那么在mybatis中如何控制事务提交呢?
- 可以使用:
session.commit();
来实现事务提交。加入事务提交后的代码如下:1
2
3
4
5
6
7@After//在测试方法执行完成之后执行
public void destroy() throws Exception{
session.commit();
//7.释放资源
session.close();
in.close();
}
(4)问题扩展:新增用户id的返回值
新增用户后,同时还要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长auto_increment的值返回。
1 | <insert id="saveUser" parameterType="USER"> |
4、用户更新
(1)在持久层接口中添加更新方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 更新用户 --> |
(3)加入更新的测试方法
1 | @Test |
5、用户删除
(1)在持久层接口中添加删除方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 删除用户 --> |
(3)加入删除的测试方法
1 | @Test |
6、用户模糊查询
(1)在持久层接口中添加模糊查询方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 根据名称模糊查询 --> |
(3)加入模糊查询的测试方法
1 | @Test |
- 在控制台输出的执行SQL语句如下:
- 在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。
(4)模糊查询的另一种配置方式
- 第一步:修改SQL语句的配置,配置如下:
1
2
3
4<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.allen.domain.User">
select * from user where username like '%${value}%'
</select>
我们在上面将原来的#{}
占位符,改成了${value}
。注意如果用模糊查询的这种写法,那么${value}
的写
法就是固定的,不能写成其它名字。
第二步:测试, 如下:
1
2
3
4
5
6
7
8
9
10
11/**
* 测试模糊查询操作
*/
@Test
public void testFindByName(){
//5.执行查询一个方法
List<User> 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。
- 通过
7、查询使用聚合函数
(1)在持久层接口中添加模糊查询方法
1 | /** |
(2)在用户的映射配置文件中配置
1 | <!-- 查询总记录条数 --> |
(3)加入聚合查询的测试方法
1 | @Test |
8、Mybatis与JDBC编程的比较
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
- 解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
- Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
- 解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
- 向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数对应。
- 解决:Mybatis 自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。
- 对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
- 解决:Mybatis 自动将 sql 执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的类型。
五、Mybatis的参数深入
1、parameterType配置参数
- 基本类型和String我们可以直接写类型名称,也可以使用包名.类名的方式,例如 :
java.lang.String
。 - 实体类类型,目前我们只能使用全限定类名。
- 究其原因,是mybaits在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。
- 在mybatis的官方文档的说明(如下图),这些都是支持的默认别名
2、传递pojo包装对象
开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
- Pojo类中包含pojo。
- 需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
(1)编写 QueryVo
1 | package com.allen.domain; |
(2)编写持久层接口
1 | /** |
(3)持久层接口的映射文件
1 | <!-- 根据用户名称模糊查询,参数变成一个 QueryVo 对象了 --> |
(4)测试包装类作为参数
1 | @Test |
六、Mybatis的输出结果封装
1、resultType配置结果类型
- resultType属性可以指定结果集的类型,它支持基本类型和实体类类型。
- 它和parameterType一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。
- 实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
(1)基本类型示例
Dao接口
1
2
3
4
5/**
* 查询总记录条数
* @return
*/
int findTotal();映射配置
1
2
3
4<!-- 查询总记录条数 -->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
(2)实体类类型示例
Dao接口
1
2
3
4
5/**
* 查询所有用户
* @return
*/
List<User> findAll();映射配置
1
2
3
4<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.allen.domain.User">
select * from user
</select>
(3)特殊情况示例
修改实体类,实体类代码如下:(此时的实体类属性和数据库表的列名已经不一致了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44/**
*用户的实体类
*/
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){
this.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;
}
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="+ userBirthday + ", userSex="+ userSex + ", userAddress=" + userAddress + "]";
}
}Dao 接口
1
2
3
4
5/**
* 查询所有用户
* @return
*/
List<User> findAll();映射配置
1
2
3
4<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.allen.domain.User">
select * from user
</select>测试查询结果
1
2
3
4
5
6
7@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
}
- 为什么名称会有值呢?
- 因为:mysql 在 windows 系统中不区分大小写!
- 修改映射配置(使用别名查询)
1
2
3
4<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.allen.domain.User">
select id as userId,username as userName,birthday as userBirthday,sex as userSex,address as userAddress from user
</select>
2、resultMap结果类型
- resultMap标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
- 在select 标签中使用resultMap属性指定引用即可。同时resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
(1)定义 resultMap
1 | <!-- 建立 User 实体和数据库表的对应关系 |
(2)测试结果
1 | @Test |
- 运行结果:
七、Mybatis传统DAO层开发(了解)
使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方式和Mapper接口代理开发方式。而现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便。现在介绍一下基于传统编写Dao实现类的开发方式。
Mybatis 实现 DAO 的传统开发方式
(1)持久层 Dao 接口
1 | /** |
(2)持久层 Dao 实现类
1 | /** |
(3)持久层映射配置
1 | <?xml version="1.0" encoding="UTF-8"?> |
(4)测试类
1 | package com.allen.test; |
八、SqlMapConfig.xml配置文件
1、配置内容
SqlMapConfig.xml中配置的内容和顺序
1 | -properties(属性) |
2、properties(属性)
在使用properties标签配置时,我们可以采用两种方式指定属性配置。
第一种
1 | <properties> |
第二种
在classpath下定义jdbc.properties文件
1
2
3
4jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/javatest?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=991104标签配置,在SqlMapConfig.xml中
1
2
3
4
5
6
7
8
9
10
11
12
13
14<!--配置properties
可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置文件信息
resource属性:
用于指定配置文件的文件,是按照类路径的写法来写,并且必须存在于类路径下
url属性:
是要求按照Url的写法来写地址
URL:Uniform Resource Locator 统一资源定位符,它是可以唯一标识一个资源的位置
它的写法:
http://localhost:8080/mybatiesserver/demo1Servlet
协议 主机 端口 URI
URI:Uniform Resource Identified 统一资源标识符。它是在应用中可以唯一定位一个资源的。
-->
<properties resource="jdbcConfig.properties">
</properties>此时dataSource标签就变成了引用上面的配置
1
2
3
4<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
3、typeAliases(类型别名)
Mybatis支持的默认别名,也可以采用自定义别名方式来开发。
(1)自定义别名
- 在SqlMapConfig.xml中配置:
1
2
3
4
5
6
7<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.allen.domain.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.allen.domain"/>
<package name="其它包"/>
</typeAliases>
4、mappers(映射器)
<mapper resource=" " />
使用相对于类路径的资源- 如:
<mapper resource="com/allen/dao/UserDao.xml" />
- 如:
<mapper class=" " />
使用 mapper 接口类路径- 如:
<mapper class="com.allen.dao.UserDao"/>
- 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
- 如:
<package name=""/>**
注册指定包下的所有 mapper 接口**- 如:
<package name="con.allen.mybatis.mapper"/>
- 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
- 如:
三张非常重要的图(对Mybatis的深入了解)
- 分析编写dao实现类Mybatis的执行过程
- 分析代理dao的执行过程
备注:
内容很充足,过两天更新下集