Mybatis 框架第一天

Mybatis 框架课程第一天

第1  章 框架 概述

1.1  什么是框架

1.1.1  什么是 框架

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。

简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

1.1.2  框架要解决的问题

框架要解决的最重要的一个问题是技术整合的问题,在 J2EE 的 框架中,有着各种各样的技术,不同的

软件企业需要从 J2EE 中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。

1.1.3  软件开发的分层重要性

框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的MVC 软件设计思想就是很好的分层思想。

 

通过分层更好的实现了各个部分的职责,在每一层将再细化出不同的框架,分别解决各层关注的问题。

1.1.4  分层开发下的常见框架

常见的 JavaEE 开发框架:

1 、解决数据的持久化问题的框架

 

作为持久层的框架,还有一个封装程度更高的框架就是Hibernate,但这个框架因为各种原因目前在国内的

流行程度下降太多,现在公司开发也越来越少使用。目前使用 Spring Data 来实现数据持久化也是一种趋势。

2 、决 解决 WEB  层问题的 MVC  框架

 

3 、解决技术整合问题

 

1.1.5 MyBatis  框架

mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,

而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

mybatis通过 xml 或注解的方式将要执行的各种statement配置起来,并通过java对象和statement 中

sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。

1.2 JDBC  编程的分析

1.2.1 jdbc  程序

public static void main(String[] args) {

Connection connection = null;

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;

try {

//加载数据库驱动

Class.forName("com.mysql.jdbc.Driver");

//通过驱动管理类获取数据库链接

connection = DriverManager

.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","ro

ot", "root");

//定义 sql 语句 ?表示占位符

String sql = "select * from user where username = ?";

//获取预处理 statement

preparedStatement = connection.prepareStatement(sql);

//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的

参数值

preparedStatement.setString(1, "王五");

//向数据库发出 sql 执行查询,查询出结果集

resultSet = preparedStatement.executeQuery();

//遍历查询结果集

while(resultSet.next()){

System.out.println(resultSet.getString("id")+"

"+resultSet.getString("username"));

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//释放资源

if(resultSet!=null){

try {

resultSet.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(preparedStatement!=null){

try {

preparedStatement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(connection!=null){

try {

connection.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

上边使用 jdbc 的原始方法(未经封装)实现了查询数据库表记录的操作。

1.2.2 jdbc  问题

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

2、Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java

代码。

3、使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。

4、对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便。

第2 章 Mybatis

通过前面的学习,我们已经能够使用所学的基础知识构建自定义的 Mybatis 框架了。这个过程是基本功的考验,我们已经强大了不少,但现实是残酷的,我们所定义的 Mybatis 框架和真正的 Mybatis 框架相比,还是显得渺小。行业内所流行的 Mybatis 框架现在我们将开启学习。

2.1 Mybatis  框架开发的准备

2.1.1  官网下载 Mybatis

 

下载的 zip 文件如下( 我们的资料文件夹):

我们所使用的 Mybatis 版本是 3.4.5 版本。

2.2  搭建 Mybatis  开发环境

2.2.1  创建 maven

创建 mybatis01 的工程,工程信息如下:

Groupid:com.hou

ArtifactId:mybatis01

Packing:jar

2.2.2  添加 Mybatis3.4.5  的坐标

在 pom.xml 文件中添加 Mybatis3.4.5 的坐标,如下:

<dependencies>

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.4.5</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.10</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.6</version>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.12</version>

</dependency>

</dependencies>

2.2.3  编写 User

public class User implements Serializable {

private Integer id;

private String username;

private Date birthday;

private String sex;

private String address;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

@Override

public String toString() {

return "User [id=" + id + ", username=" + username + ", birthday=" + birthday

+ ", sex=" + sex + ", address="

+ address + "]";

}

}

2.2.4  编写 持久层 接口 IUserDao

IUserDao 接口就是我们的持久层接口(也可以写成 UserDao 或者 UserMapper),具体代码如下:

public interface IUserDao {

List<User> findAll();

}

2.2.5  编写 持久层接口的 映射文件 IUserDao.xml

要求:

创建位置:必须和持久层接口在相同的包中。

名称:必须以持久层接口名称命名文件名,扩展名是.xml

<?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.hou.dao.IUserDao">

<!-- 配置查询所有操作 -->

<select id="findAll" resultType="com.hou.domain.User">

select * from user

</select>

2.2.6  编写 SqlMapConfig.xml

<?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">

<!-- 配置 mysql 的环境 -->

<environment id="mysql">

<!-- 配置事务的类型 -->

<transactionManager type="JDBC"></transactionManager>

<!-- 配置连接数据库的信息:用的是数据源(连接池) -->

<dataSource type="POOLED">

<property name="driver" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/ee50"/>

<property name="username" value="root"/>

<property name="password" value="1234"/>

</dataSource>

</environment>

</environments>

<!-- 告知 mybatis 映射配置的位置 -->

<mappers>

<mapper resource="com/hou/dao/IUserDao.xml"/>

</mappers>

</configuration>

2.2.7编写测试类

public class MybatisTest {

public static void main(String[] args)throws Exception {

//1.读取配置文件

InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");

//2.创建 SqlSessionFactory 的构建者对象

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//3.使用构建者创建工厂对象 SqlSessionFactory

SqlSessionFactory factory = builder.build(in);

//4.使用 SqlSessionFactory 生产 SqlSession 对象

SqlSession session = factory.openSession();

//5.使用 SqlSession 创建 dao 接口的代理对象

IUserDao userDao = session.getMapper(IUserDao.class);

//6.使用代理对象执行查询所有方法

List<User> users = userDao.findAll();

for(User user : users) {

System.out.println(user);

}

//7.释放资源

session.close();

in.close();

}

}

2.3  小结

通过快速入门示例,我们发现使用 mybatis 是非常容易的一件事情,因为只需要编写 Dao 接口并且按照

mybatis 要求编写两个配置文件,就可以实现功能。远比我们之前的 jdbc 方便多了。(我们使用注解之后,将变得更为简单,只需要编写一个 mybatis 配置文件就够了。)

但是,这里面包含了许多细节,比如为什么会有工厂对象(SqlSessionFactory),为什么有了工厂之后还

要有构建者对象(SqlSessionFactoryBuilder),为什么 IUserDao.xml 在创建时有位置和文件名的要求等等。这些问题我们在自定义 mybatis 框架的章节,通过层层剥离的方式,给大家讲解。

请注意:我们讲解自定义 Mybatis 框架,不是让大家回去自己去写个 mybatis,而是让我们能更好了了解mybatis 内部是怎么执行的,在以后的开发中能更好的使用 mybatis 框架,同时对它的设计理念(设计模式)有一个认识。

2.4  补充 (基于注解的 mybatis)

2.4.1在持久层接口中添加注解

public interface IUserDao {

@Select("select * from user")

List<User> findAll();

}

2.4.2  修改 SqlMapConfig.xml

<mappers>

<mapper class="com.hou.dao.IUserDao"/>

</mappers>

2.4.3  注意事项:

在使用基于注解的 Mybatis 配置时,请移除 xml 的映射配置(IUserDao.xml)。

第3 章 基于代理 Dao  实现 CRUD  操作

使用要求:

1、持久层接口和持久层接口的映射配置必须在相同的包下

2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名

3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的

方法名相同。

2.1  根据 ID  查询

2.1.1  在 持久层接口 中添加 findById

/**

* 根据 id 查询

* @param userId

* @return

*/

User findById(Integer userId);

2.1.2  在用户的映射配置文件中配置

<!-- 根据 id 查询 -->

<select id="findById" resultType="com.hou.domain.User" parameterType="int">

select * from user where id = #{uid}

</select>

细节:

resultType  属性:

用于指定结果集的类型。

parameterType属性:

用于指定传入参数的类型。

sql  语句中使用#{} 字符 :

它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。

具体的数据是由#{}里面的内容决定的。

#{} 中内容的写法:

由于数据类型是基本类型,所以此处可以随意写。

2.1.3在测试类添加测试

public class MybastisCRUDTest {

private InputStream in ;

private SqlSessionFactory factory;

private SqlSession session;

private IUserDao userDao;

@Test

public 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();

}

}

2.2  保存操作

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

/**

* 保存用户

* @param user

* @return 影响数据库记录的行数

*/

int saveUser(User user);

2.2.2  在 用户的映射配置文件中 配置

<!-- 保存用户-->

<insert id="saveUser" parameterType="com.hou.domain.User">

insert into user(username,birthday,sex,address)

values(#{username},#{birthday},#{sex},#{address})

</insert>

细节:

parameterType 属性:

代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。

sql 语句中使用#{}字符:

它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。

具体的数据是由#{}里面的内容决定的。

#{}中内容的写法:

由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称。

它用的是 ognl 表达式。

ognl 表达式:

它是 apache 提供的一种表达式语言,全称是:

Object Graphic Navigation Language 对象图导航语言

它是按照一定的语法格式来获取数据的。

语法格式就是使用 #{对象.对象}的方式

#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用

getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.

而直接写 username。

2.2.3添加测试类中的测试方法

@Test

public 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();

}

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

新增用户后,同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相

当于我们要在新增后将自动增长 auto_increment 的值返回。

<insert id="saveUser" parameterType="USER">

<!--  配置保存时获取插入的 id -->

<selectKey keyColumn="id" keyProperty="id" resultType="int">

select last_insert_id();

</selectKey>

insert into user(username,birthday,sex,address)

values(#{username},#{birthday},#{sex},#{address})

</insert>

2.3  用户 更新

2.3.1  在 持久层接口

/**

* 更新用户

* @param user

* @return 影响数据库记录的行数

*/

int updateUser(User user);

<!-- 更新用户 -->

<update id="updateUser" parameterType="com.hou.domain.User">

update user set username=#{username},birthday=#{birthday},sex=#{sex},

address=#{address} where id=#{id}

</update>

2.3.3  加入更新的测试方法

@Test

public void testUpdateUser()throws Exception{

//1.根据 id 查询

User user = userDao.findById(52);

//2.更新操作

user.setAddress("北京市顺义区");

int res = userDao.updateUser(user);

System.out.println(res);

}

2.4  用户删除

2.4.1  在 持久层接口 中添加 删除方法

/**

* 根据 id 删除用户

* @param userId

* @return

*/

int deleteUser(Integer userId);

2.4.2  在 用户的映射配置 文件中

<!-- 删除用户 -->

<delete id="deleteUser" parameterType="java.lang.Integer">

delete from user where id = #{uid}

</delete>

2.4.3加入删除的测试方法

@Test

public void testDeleteUser() throws Exception {

//6.执行操作

int res = userDao.deleteUser(52);

System.out.println(res);

}

2.5用户模糊查询

2.5.1  在 持久层接口 中添加 模糊查询方法

/**

* 根据名称模糊查询

* @param username

* @return

*/

List<User> findByName(String username);

2.5.2  在 用户的映射配置 文件中

<!-- 根据名称模糊查询 -->

<select id="findByName" resultType="com.hou.domain.User" parameterType="String">

select * from user where username like #{username}

</select>

2.5.3  加入模糊查询的测试方法

@Test

public void testFindByName(){

//5.执行查询一个方法

List<User> users = userDao.findByName("%王%");

for(User user : users){

System.out.println(user);

}

}

在控制台输出的执行 SQL 语句如下:

 

我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标

识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。

2.5.4  模糊查询的另一种配置方式

第一步:修改 SQL 语句的配置,配置如下:

<!-- 根据名称模糊查询 -->

<select id="findByName" parameterType="string" resultType="com.hou.domain.User">

select * from user where username like '%${value}%'

</select>

我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写

法就是固定的,不能写成其它名字。

第二步:测试,如下:

/**

* 测试模糊查询操作

*/

@Test

public void testFindByName(){

//5.执行查询一个方法

List<User> users = userDao.findByName("王");

for(User user : users){

System.out.println(user);

}

}

在控制台输出的执行 SQL 语句如下:

 

 

可以发现,我们在程序代码中就不需要加入模糊查询的匹配符%了,这两种方式的实现效果是一样的,但执行的语句是不一样的。

2.5.5 #{} 与${} 的区别

#{} 表示一个占位符号

通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,

#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类

型值,#{}括号中可以是 value 或其它名称。

${} 表示拼接 sql  串

通过${}可以将 parameterType 传入的内容拼接在 sql中且不进行 jdbc 类型转换, ${}可以接收简

单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

2.5.6  模糊查询的${value}

我们一起来看 TextSqlNode 类的源码:

 

这就说明了源码中指定了读取的 key 的名字就是”value”,所以我们在绑定参数时就只能叫 value 的名字

了。

2.6  查询使用聚合函数

2.6.1  在 持久层接口 中添加 模糊查询方法

/**

* 查询总记录条数

* @return

*/

int findTotal();

2.6.2  在 用户的映射配置 文件中配置

<!-- 查询总记录条数 -->

<select id="findTotal" resultType="int">

select count(*) from user;

</select>

2.6.3  加入 聚合 查询的测试方法

@Test

public void testFindTotal() throws Exception {

//6.执行操作

int res = userDao.findTotal();

System.out.println(res);

}

2.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 定义输出结果的

类型。

第3  章 s Mybatis  的参数深入

3.1  parameterType  配置

3.1.1  使 用说明

我们在上一章节中已经介绍了 SQL 语句传参,使用标签的 parameterType 属性来设定。该属性的取值可以

是基本类型,引用类型(例如:String 类型),还可以是实体类类型(POJO 类)。同时也可以使用实体类的包装类,本章节将介绍如何使用实体类的包装类作为参数传递。

3.1.2  注意 事项

基 本类 型和 String 我 们可 以直接 写类型 名称 ,也 可以 使用包 名 . 类名的 方式 ,例如 :

java.lang.String。

实体类类型,目前我们只能使用全限定类名。

究其原因,是 mybaits 在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,

而我们的是实体类并没有注册别名,所以必须写全限定类名。在今天课程的最后一个章节中将讲解如何注册实体类的别名。

 

这些都是支持的默认别名。我们也可以从源码角度来看它们分别都是如何定义出来的。

可以参考 TypeAliasRegistery.class 的源码。

 

3.2  传递 pojo  包装对象

开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查

询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

Pojo 类中包含 pojo。

需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。

3.2.1  编写 QueryVo

public class QueryVo implements Serializable {

private User user;

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

}

3.2.2  编写持久层 接口

public interface IUserDao {

/**

* 根据 QueryVo 中的条件查询用户

* @param vo

* @return

*/

List<User> findByVo(QueryVo vo);

}

3.2.3  持久层接口的映射 文件

<!-- 根据用户名称模糊查询,参数变成一个 QueryVo 对象了 -->

<select id="findByVo" resultType="com.hou.domain.User"

parameterType="com.hou.domain.QueryVo">

select * from user where username like #{user.username};

</select>

3.2.4  测试包装类作为参数

@Test

public void testFindByQueryVo() {

QueryVo vo = new QueryVo();

User user = new User();

user.setUserName("%王%");

vo.setUser(user);

List<User> users = userDao.findByVo(vo);

for(User u : users) {

System.out.println(u);

}

}

第4 章 Mybatis  的输出结果封装

4.1  resultType  配置结果类型

resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。

我们在前面的 CRUD 案例中已经对此属性进行过应用了。

需要注意的是,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。例如:我们的实体类此时必须是全限定类名(今天最后一个章节会讲解如何配置实体类的别名)同时,当是实体类名称是,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。

4.1.1基本类型示例

4.1.1.1 Dao  接口

/**

* 查询总记录条数

* @return

*/

int findTotal();

4.1.1.2  映射配置

<!-- 查询总记录条数 -->

<select id="findTotal" resultType="int">

select count(*) from user;

</select>

4.1.2实体类类型示例

4.1.2.1 Dao  接口

/**

* 查询所有用户

* @return

*/

List<User> findAll();

4.1.2.2  映射配置

<!-- 配置查询所有操作 -->

<select id="findAll" resultType="com.hou.domain.User">

select * from user

</select>

4.1.3  特殊情况示例

4.1.3.1  修改实体类

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 + "]";

}

}

4.1.3.2 Dao  接口

/**

* 查询所有用户

* @return

*/

List<User> findAll();

4.1.3.3  映射配置

<!-- 配置查询所有操作 -->

<select id="findAll" resultType="com.hou.domain.User">

select * from user

</select>

4.1.3.4测试查询结果

@Test

public void testFindAll() {

List<User> users = userDao.findAll();

for(User user : users) {

System.out.println(user);

}

}

 

为什么名称会有值呢?

因为:mysql 在 windows  系统中不区分大小写

4.1.3.5  修改映射配置

使用别名查询

<!-- 配置查询所有操作 -->

<select id="findAll" resultType="com.hou.domain.User">

select id as userId,username as userName,birthday as userBirthday,

sex as userSex,address as userAddress from user

</select>

运行结果:

思考:

如果我们的查询很多,都使用别名的话写起来岂不是很麻烦,有没有别的解决办法呢?

请看下一小节。

4.2  resultMap  结果类型

resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。

在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。

4.2.1  定义 resultMap

<!-- 建立 User 实体和数据库表的对应关系

type 属性:指定实体类的全限定类名

id 属性:给定一个唯一标识,是给查询 select 标签引用用的。

-->

<resultMap type="com.hou.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 属性:用于指定实体类属性名称

4.2.2  映射配置

<!-- 配置查询所有操作 -->

<select id="findAll" resultMap="userMap">

select * from user

</select>

4.2.3  测试结果

@Test

public void testFindAll() {

List<User> users = userDao.findAll();

for(User user : users) {

System.out.println(user);

}

}

运行结果:

第5章 SqlMapConfig.xml 配置文件

5.1  配置内容

5.1.1 SqlMapConfig.xml  中配置的内容和顺序

-properties (属性)

--property

-settings(全局配置参数)

--setting

-typeAliases (类型别名)

--typeAliase

--package

-typeHandlers(类型处理器)

-objectFactory(对象工厂)

-plugins(插件)

-environments(环境集合属性对象)

--environment(环境子属性对象)

---transactionManager(事务管理)

---dataSource(数据源)

-mappers (映射器)

--mapper

--package

6.2 properties

在使用 properties 标签配置时,我们可以采用两种方式指定属性配置。

6.2.1  第一种

<properties>

<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>

<property name="jdbc.url" value="jdbc:mysql://localhost:3306/eesy"/>

<property name="jdbc.username" value="root"/>

<property name="jdbc.password" value="1234"/>

</properties>

6.2.2  第二种

6.2.2.1 在 在 classpath  下定义 db.properties  文件

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/eesy

jdbc.username=root

jdbc.password=1234

6.2.2.2 properties  标签配置

<!-- 配置连接数据库的信息

resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下

resource="jdbcConfig.properties"

url 属性:

URL: Uniform Resource Locator 统一资源定位符

http://localhost:8080/mystroe/CategoryServlet URL

协议 主机 端口  URI

URI:Uniform Resource Identifier 统一资源标识符

/mystroe/CategoryServlet

它是可以在 web 应用中唯一定位一个资源的路径

-->

<properties  url=

file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.prop

erties">

</properties>

6.2.3  此时我们的 dataSource标签就变成了引用上面的配置

<dataSource type="POOLED">

<property name="driver" value="${jdbc.driver}"/>

<property name="url" value="${jdbc.url}"/>

<property name="username" value="${jdbc.username}"/>

<property name="password" value="${jdbc.password}"/>

</dataSource>

6.3 typeAliases (类型别名)

在前面我们讲的 Mybatis 支持的默认别名,我们也可以采用自定义别名方式来开发。

6.3.1  自定义别名:

在 SqlMapConfig.xml 中配置:

<typeAliases>

<!-- 单个别名定义 -->

<typeAlias alias="user" type="com.hou.domain.User"/>

<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->

<package name="com.hou.domain"/>

<package name=" 其它包 "/>

</typeAliases>

6.4 mappers (映射器)

6.4.1 <mapper resource=" " />

使用相对于类路径的资源

如:<mapper resource="com/hou/dao/IUserDao.xml" />

 

6.4.2 <mapper class=" " />

使用 mapper 接口类路径

如:<mapper class="com.hou.dao.UserDao"/>

注意:此种方法要求 r mapper  接口名称和 r mapper  映射文件名称相同,且放在同一个目录中。

6.4.3 <package name=""/>

注册指定包下的所有 mapper 接口

如:<package name="cn.hou.mybatis.mapper"/>

注意:此种方法要求  mapper  接口名称和  mapper

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值