欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mybatis框架总结(二)

程序员文章站 2024-03-19 18:13:16
...

第1章 回顾

1.1 自定义Mybatis框架流程再分析

第一步:SqlSessionFactoryBuilder接收SqlMapConfig.xml文件流,构建出SqlSessionFactory对象。

	//1.读取配置文件
	InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
	//2.创建 SqlSessionFactory 的构建者对象
	SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
	//3.使用构建者创建工厂对象 SqlSessionFactory
	SqlSessionFactory factory = builder.build(in);

第二步:SqlSessionFactory读取SqlMapConfig.xml中连接数据库和Mapper映射信息,用来生产出操作数据库的SqlSession对象。

	//4.使用 SqlSessionFactory 生产 SqlSession 对象
	SqlSession session = factory.openSession();

第三步:SqlSession对象的两大作用:

  • 作用(1):创建接口代理对象
    在SqlSessionImpl对象的getMapper方法中分两步实现:
    第一:先用SqlSessionFactory读取数据库连接信息创建Connection对象。
    第二:通过jdk代理模式创建代理对象作为getMapper的返回值。 创建代理对象时,得到sql语句执行对应的CRUD操作。
	//5.使用 SqlSession 创建 dao 接口的代理对象
	IUserDao userDao = session.getMapper(IUserDao.class);
  • 作用(2):定义通用的增删改查方法
    在SqlSessionImpl对象中提供selectList方法(Mybatis还有其他方法)分为两步
    第一:用SqlSessionFactory读取数据库连接信息创建Connection对象。
    第二:直接得到sql语句,使用jdbc的Connection对象进行对应的CRUD操作。

第四步:封装结果集
无论使用创建代理对象还是使用提供的通用CRUD方法,都要数据库结果集进行封装,变成Java对象返回给调用者,故必须知道调用者的返回类型。

	//6.使用代理对象执行查询所有方法
	List<User> users = userDao.findAll();
	for(User user : users) {
		System.out.println(user);
	}

总结:
无论使用创建代理对象还是使用提供的通用CRUD方法,本质就是得到jdbc的Connection对象,执行对应的sql语句,最终对数据库结果集进行封装。
Mybatis框架总结(二)

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

2.1.1 在持久层接口(Dao)中添加方法

例如:

/**
* 根据 id 查询
* @param userId
* @return
*/
User findById(Integer userId);

2.1.2 在(IUserDao.xml)映射配置文件中进行配置

<!-- 根据 id 查询 --> 
	<select id="findById" resultType="com.itheima.domain.User" parameterType="int">
		select * from user where id = #{uid}
	</select>
细节:
resultType 属性:
	用于指定结果集的类型。
parameterType 属性:
	用于指定传入参数的类型。
sql 语句中使用#{}字符: 它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
具体的数据是由#{}里面的内容决定的。
#{}中内容的写法:
	由于数据类型是基本类型,所以此处可以随意写。
	如果保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称。它用的是 ognl 表达式。
	ognl 表达式:它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 对象图导航语言
	它是按照一定的语法格式来获取数据的。
	语法格式就是使用 #{对象.对象}的方式
	#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是如果我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.而直接写 username
	
<!-- 保存用户--> 
	<insert id="saveUser" parameterType="com.itheima.domain.User">
		insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
	</insert>

2.1.3 添加测试类

/**
* 
* <p>Title: MybastisCRUDTest</p>
* <p>Description: 测试 mybatis 的 crud 操作</p>
* <p>Company: http://www.itheima.com/ </p>
*/
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);
}

@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);
}

@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{
//在测试增删改时,需要增加事务控制的提交,和jdbc一样
session.commit();
//7.释放资源
session.close();
in.close();
	} 
}

在测试增删改时,需要增加事务控制的提交,和jdbc一样

2.1.4 问题拓展:新增用户时,返回该新用户的ID

配置IUserDao.xml

<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.2 用户的模糊查询

2.2.1 方式一:配置文件中不加模糊条件,传入实参加上模糊标识%

1.映射配置文件配置

<!-- 根据名称模糊查询 --> <select id="findByName" resultType="com.itheima.domain.User" parameterType="String">
	//这里没有加模糊标识
 	select * from user where username like #{username}
</select>

2. 测试方法中传入实参时加入模糊标识

@Test
 public void testFindByName(){
 	//5.执行查询一个方法
 	List<User> users = userDao.findByName("%王%");
 	for(User user : users){
 	System.out.println(user);
	 }
 }

2.2.2 映射配置文件中加入模糊标识,测试方法传入实参不加模糊标识

1.映射配置文件加入模糊标识
这里的%${value}%为固定写法

<!-- 根据名称模糊查询 --> 
<select id="findByName" parameterType="string" 	resultType="com.itheima.domain.User">
 	select * from user where username like '%${value}%'
</select>
  1. 测试方法中的传入实参不加模糊标识
	@Test
	public void testFindByName(){
	 //5.执行查询一个方法
	List<User> users = userDao.findByName("王");
	for(User user : users){
		System.out.println(user);
	} 
}

2.2.3 #{}与${} 的区别

#{}表示一个占位符号

通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。

${}表示拼接 sql 串

通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

2.3 Myabtis与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章 Mybatis的参数深入

3.1 parameterType配置参数(代表参数类型)

<!-- 保存用户--> 
<insert id="saveUser" parameterType="com.itheima.domain.User">
	insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>

该属性的取值:

  1. 基本类型
  2. 引用类型(例如:String 类型)
  3. 实体类类型(POJO 类)
  4. 实体类的包装类
    注意:
  • 基 本 类 型 和 String 我 们 可 以 直 接 写 类 型 名 称 , 也 可 以 使 用 包 名 . 类 名 的 方 式 , 例 如 :java.lang.String。
  • 实体类类型,目前我们只能使用全限定类名。

第4章 Mybatis的输出结果封装

4.1 resultType配置结果类型

	<!-- 查询总记录条数 --> 
	<select id="findTotal" resultType="int">
		select count(*) from user;
	</select>

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

注意:

  • 和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。
  • 没有注册过的必须使用全限定类名。例如:我们的实体类此时必须是全限定类名,
  • 还有一个要求:实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装

4.2 resultMap结果类型

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

4.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 属性:用于指定实体类属性名称

4.2.2 映射配置文件

<!-- 配置查询所有操作 --> 
	//这里的resultMap值与定义在resultMap中的 id一致。
	<select id="findAll" resultMap="userMap">
		select * from user
	</select>

第5章 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>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置msql的环境-->
        <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/eesy_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--配置映射文件位置-->
    <mappers>
        <mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
    </mappers>

</configuration>

5.1 properties属性

5.1.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>

5.1.2 方式二(使用db.properties文件)比较推荐

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234

5.1.3 映射文件中配置

properties标签:

<!-- 配置连接数据库的信息
	resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下
			resource="jdbcConfig.properties"
	url 属性:统一资源定位符
	--> 
	<properties resource = "db.properties">
	</properties>
	<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>

5.3 typeAliasea(类型别名)

5.4 mappers(映射器)

5.4.1 <mapper resource=" " / >

 <!--配置映射文件位置-->
    <mappers>
        <mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
    </mappers>

5.4.2 <mapper class=" " / >

使用注解方式时:

<!--配置映射文件位置-->
    <mappers>
        <mapper class="com.itheima.dao.IUserDao"></mapper>
    </mappers>