1 参数深入
1.1 parameterType配置参数
1.1.1 使用说明
我们在上一章节中已经介绍了SQL语句传参,使用标签的parameterType属性来设定。该属性的取值可以是基本类型,引用类型(例如:String类型),还可以是实体类类型(POJO类)。同时也可以使用实体类的包装类,本章节将介绍如何使用实体类的包装类作为参数传递。
1.1.2 注意事项
-
基本类型和String:我们可以直接写类型名称,也可以使用全限定类名方式。
例如:java.lang.String。 -
实体类类型:目前我们只能使用全限定类名。
究其原因,是MyBatis在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。后续将讲解如何注册实体类的别名 → 见MyBatis的官方文档(第19页)
这些都是支持的默认别名。我们也可以从源码角度来看它们分别都是如何定义出来的。
可以参考TypeAliasRegistery.class
的源码:
1.2 传递POJO包装对象
开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。POJO类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
1.2.1 编写QueryVo
/**
* <p>Title: QueryVo</p>
* <p>Description: 查询条件对象</p>
* <p>Company: http://www.itheima.com/</p>
*/
public class QueryVo implements Serializable {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
1.2.2 编写持久层接口
/**
* <p>Title: IUserDao</p>
* <p>Description: 用户的业务层接口</p>
* <p>Company: http://www.itheima.com/ </p>
*/
public interface IUserDao {
/**
* 根据QueryVo中的条件查询用户
* @param vo
* @return
*/
List<User> findByVo(QueryVo vo);
}
1.2.3 持久层接口的映射文件
<!-- 根据用户名称模糊查询,参数变成一个QueryVo对象了 -->
<select id="findByVo" resultType="com.itheima.domain.User" parameterType="com.itheima.domain.QueryVo">
select * from user where username like #{user.username};
</select>
1.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);
}
}
2 输出结果封装:resultType配置结果类型
resultType属性可以指定结果集的类型,它支持基本类型和实体类类型。我们在前面的CRUD案例中已经对此属性进行过应用了。
需要注意的是,它和parameterType一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。例如:我们的实体类此时必须是全限定类名。
当是实体类名称时,还有一个要求:实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
2.1 基本类型示例
2.1.1 Dao接口
/**
* 查询总记录条数
* @return
*/
int findTotal();
2.1.2 映射配置
<!-- 查询总记录条数 -->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
2.2 实体类类型示例
2.2.1 Dao接口
/**
* 查询所有用户
* @return
*/
List<User> findAll();
2.2.2 映射配置
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>
2.3 特殊情况示例
2.3.1 修改实体类属性名
此时实体类属性名 userName
;
相应数据库表列名 username
,不一致。
/**
* <p>Title: User</p>
* <p>Description: 用户的实体类</p>
*/
public class User implements Serializable {
......
private String userName;
......
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
......
}
2.3.2 测试查询结果
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
}
为什么名称会有值呢? 因为:MySQL在Windows系统中不区分大小写!
2.3.3 解决方法1:修改映射配置
使用别名查询:
<!-- 配置查询所有操作 -->
<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>
运行结果:
思考:如果我们的查询很多,都使用别名的话写起来岂不是很麻烦,有没有别的解决办法呢? 请看下一小节。
2.3.4 解决方法2:resultMap结果类型
resultMap标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在select标签中使用resultMap属性指定引用即可。同时resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
2.3.4.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属性:用于指定实体类属性名称。
2.3.4.2 映射配置
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>
2.3.4.3 测试结果
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
}
运行结果:
3 SqlMapConfig.xml配置文件
3.1 配置内容
3.1.1 SqlMapConfig.xml中配置的内容和顺序
- properties(属性)
- property
- settings(全局配置参数)
- setting
- typeAliases(类型别名)
- typeAliase
- package ★
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
- environment(环境子属性对象)
- mappers(映射器)
- mapper
- package ★
3.2 properties(属性)
在使用properties标签配置时,我们可以采用两种方式指定属性配置。
-
第一种:
<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>
-
第二种:
-
在classpath下定义
db.properties
文件:jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/eesy jdbc.username=root jdbc.password=1234
-
properties标签配置:
- resource属性:用于指定properties配置文件的位置,要求配置文件必须在类路径下:
<!-- 配置连接数据库的信息 --> <properties resource="jdbcConfig.properties"> </properties>
- url属性:
<!-- 配置连接数据库的信息 --> <properties url=file:///D:/IdeaProjects/mybatisCRUD/src/main/resources/jdbcConfig.properties "> </properties>
- URI(Uniform Resource Identifier 统一资源标识符):在web应用中唯一定位一个资源的路径。
/mystroe/CategoryServlet - URL(Uniform Resource Locator 统一资源定位符):
http://localhost:8080/mystroe/CategoryServlet
协议 主机 端口 URI
- URI(Uniform Resource Identifier 统一资源标识符):在web应用中唯一定位一个资源的路径。
此时我们的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>
- resource属性:用于指定properties配置文件的位置,要求配置文件必须在类路径下:
-
3.3 typeAliases(类型别名)
在前面我们讲的MyBatis支持的默认别名,我们也可以采用自定义别名方式来开发。
在 SqlMapConfig.xml
中配置:
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.itheima.domain.User" />
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.itheima.domain" />
</typeAliases>
- typeAlias:用于配置别名。
- type属性:指定的是实体类全限定类名;
- alias属性:指定别名,当指定了别名就不再区分大小写。
- package:用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写
3.4 mappers(映射器)
在 SqlMapConfig.xml
中配置:
<!-- 配置映射文件的位置 -->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml" />
<package name="com.itheima.dao" />
</mappers>
- mapper:
-
resource属性:使用相对于类路径的资源。
<mapper resource="com/itheima/dao/IUserDao.xml" />
-
class属性:使用dao接口类路径。
<mapper class="com.itheima.dao.UserDao" />
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
-
- package:注册指定包下的所有dao接口,之后就不需要在写mapper以及resource或者class了。
注意:此种方法要求dao接口名称和dao映射文件名称相同,且放在同一个目录中。