非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿
什么是Mybatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
单独使用jdbc开发存在的问题
实现步骤
- 加载数据库驱动。根据不同的数据库选择不同的驱动。
- 创建一个连接。获得一个Connection对象。
- 创建一个prepareStatement对象,封装了sql语句。
- 设置参数。
- 执行查询获得一个ResultSet对象。
- 遍历resultSet对象。
数据库
代码实现
存在的问题
- 数据库驱动存在硬编码的问题。写到配置文件中来解决。
- 数据库连接串、用户名、密码存在硬编码的问题。
- Sql语句硬编码
- 参数设置不灵活
- 查询结果最好是返回一个pojo对象或者是pojo列表。
- 每次查询都需要开启连接关闭连接。浪费性能。需要使用数据库连接池。
Mybatis框架架构
Mybatis的入门程序
Mybatis的下载
mybatis的代码由github.comg管理,地址:https://github.com/mybatis/mybatis-3/releases
需求
实现以下功能:
根据用户id查询一个用户信息
根据用户名称模糊查询用户信息列表
添加用户
更新用户
删除用户
入门程序实现
工程搭建
第一步:创建一个java工程。
第二步:导入jar包。包括mybatis的jar包、mybatis依赖的jar包、mysql的数据库驱动。
第三步:创建一个log4j.properties。方便查看sql语句用的。
第四步:创建一个SqlMapConfig.xml。配置数据库连接池。
第五步:创建Mapper映射文件。
第六步:编码。
SqlMapConfig.xml
在classpath下创建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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
</mappers>
</configuration>
Mapper映射文件
习惯上mapper映射文件的名称和数据库的表名一致。Ibatis时代的习惯。
<?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">
<!-- namespace的作用就是sql语句隔离,后面还有其他用途。 -->
<mapper namespace="test">
</mapper>
在SqlMapConfig.xml中加载mapper映射文件
<!-- 加载Mapper映射文件 -->
<mappers>
<!-- resource从classpath下开始查找 -->
<mapper resource="sqlmap/user.xml"/>
</mappers>
根据用户id查询一个用户信息
创建一个POJO保存返回结果
POJO的属性要求和数据库中的字段相对应
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
//set和get方法
}
Sql语句
select * from user where id = 10
Mapper文件
需要把sql语句写到user.xml这个mapper映射文件中
<?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">
<!-- namespace的作用就是sql语句隔离,后面还有其他用途。 -->
<mapper namespace="test">
<!--
select:如果是一个select语句就需要使用select节点。
id就是一个sql语句的id,代表一个sql语句。起个名字叫做StatementId。
parameterType:参数的类型
resultType:返回结果的类型,可以是pojo类型,需要pojo的全限定名。
#{}:是一个占位符。相当于jdbc中的“?”,括号内容的名称,如果是简单数据类型可以随便起。
-->
<select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
SELECT * from user where id = #{id}
</select>
</mapper>
查询方法
/**
* 根据id查询用户信息
*/
@Test
public void getUserById() throws Exception {
//创建一SqlSessionFactory
//把配置文件读取到流中
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//创建sqlsession对象
SqlSession sqlSession = sessionFactory.openSession();
//查询一条记录使用selectOne方法
//第一个参数:statementID
//第二个参数:sql语句用到的参数
User user = sqlSession.selectOne("test.getUserById", 10);
System.out.println(user);
//关闭sqlsession
sqlSession.close();
}
根据用户名查询用户
Sql语句
SELECT * from user where username LIKE '%张三%'
第一种方法
Mapper文件
<!-- 根据用户名查询用户 -->
<!-- resultType是返回结果中一条记录的类型 -->
<select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
SELECT * from user where username LIKE #{name}
</select>
测试方法
@Test
public void getUserByName() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//返回结果是多条记录使用selectList
List<User> userList = sqlSession.selectList("test.getUserByName", "%张三%");
System.out.println(userList);
sqlSession.close();
}
第二种方法
Mapper文件
<!-- 根据用户名查询用户 -->
<!-- resultType是返回结果中一条记录的类型 -->
<!-- ${}:字符串拼接指令。可以拼装成一个完整的sql语句。缺点不能防止sql注入
${}内部的名称,如果是简单数据类型,必须是value
-->
<select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
<!-- SELECT * from user where username LIKE #{name} -->
SELECT * from user where username LIKE '%${value}%'
</select>
测试方法
@Test
public void getUserByName() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//返回结果是多条记录使用selectList
//List<User> userList = sqlSession.selectList("test.getUserByName", "%张三%");
List<User> userList = sqlSession.selectList("test.getUserByName", "张三");
System.out.println(userList);
sqlSession.close();
}
添加用户
Sql语句
INSERT INTO user`(username,birthday,sex,address) VALUES('','','','')
Mapper文件
<!-- 添加用户 -->
<!-- 取对象中的属性直接使用#{}来取,括号中的名称必须是对象的属性名 -->
<insert id="insertUser" parameterType="cn.itcast.pojo.User">
INSERT INTO `user`(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
测试方法
@Test
public void insertUser() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//添加用户
User user = new User();
user.setUsername("入云龙");
user.setSex("1");
user.setAddress("天津蓟县");
user.setBirthday(new Date());
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close();
}
主键返回
在mysql中可以使用SELECT LAST_INSERT_ID();方法取当前事务中最后生成的id。在mybatis可以使用主键返回方法,把主键取出来返回给java程序。
<!-- 添加用户 -->
<!-- 取对象中的属性直接使用#{}来取,括号中的名称必须是对象的属性名 -->
<insert id="insertUser" parameterType="cn.itcast.pojo.User">
<!-- keyProperty:user对象的主键属性
resultType:主键的数据类型
order:取主键语句的执行时机。BEFORE:在插入之前执行 AFTER:插入之后执行
-->
<selectKey keyProperty="id" resultType="int" order="AFTER">
<!-- mysql取主键的函数 -->
SELECT LAST_INSERT_ID();
</selectKey>
INSERT INTO `user`(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
修改用户
Sql语句
UPDATE USER SET username = ' ', birthday= ' ', sex= ' ', address = '' WHERE id= 10
Mapper文件
<!-- 修改用户信息 -->
<update id="updateUser" parameterType="cn.itcast.pojo.User">
UPDATE USER
SET username = #{username},
birthday = #{birthday},
sex = #{sex},
address = #{address}
WHERE
id = #{id}
</update>
测试方法
@Test
public void updateUser() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//取用户信息
User user = sqlSession.selectOne("test.getUserById", 28);
user.setUsername("武松");
user.setAddress("清河县");
sqlSession.update("test.updateUser", user);
//提交修改
sqlSession.commit();
sqlSession.close();
}
删除用户
Sql语句
DELETE from user where id=10
Mapper文件
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
DELETE from user where id=#{id}
</delete>
测试方法
@Test
public void deleteUserById() {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.delete("test.deleteUserById", 28);
sqlSession.commit();
sqlSession.close();
}
Mybatis和Hibernate的区别
- Mybatis并不是一个完全的orm框架。Hibernate是面向对象,可以不使用sql语句。Mybatis是面向sql语句的。专注的是输入映射返回值映射以及sql语句的灵活性。
- Mybatis门槛比较低,学习起来比较简单。查询性能,hibernate需要对性能进行优化,需要一个高手。Mybatis只需要对sql优化即可。
- Hibernate主要是应用在传统项目,开发速度很快。Mybatis主要用于互联网领域。适用于变化比较快的领域。
- 选择框架时,根据团队的技术储备。选择比较熟悉的框架。
使用Mybatis开发dao的方法
Sqlsession应用范围
Sqlsession
本身是线程不安全的,最佳应用范围应该是方法级别。
SqlsessionFactory
工厂类,创建Sqlsession的。此对象应该是单例模式出现在系统中,一个系统中只有一个SqlsessionFactory对象。
SqlsessionFactoryBuilder
当做一个工具类使用,创建完SqlsessionFactory对象就不用了。
传统方式
接口+实现类的方式
Dao
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sessionFactory;
//构造方法中注入SqlSessionFactory对象。
public UserDaoImpl(SqlSessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public User getUserById(int id) {
SqlSession sqlSession = sessionFactory.openSession();
User user = sqlSession.selectOne("test.getUserById", id);
sqlSession.close();
return user;
}
@Override
public List<User> getUserByName(String name) {
SqlSession sqlSession = sessionFactory.openSession();
List<User> userList = sqlSession.selectList("test.getUserByName", name);
sqlSession.close();
return userList;
}
@Override
public void insertUser(User user) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close();
}
}
测试方法
public class UserDaoTest {
private SqlSessionFactory sessionFactory;
@Before
public void init() throws Exception {
// 创建一SqlSessionFactory
// 把配置文件读取到流中
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testGetUserById() {
UserDao userDao = new UserDaoImpl(sessionFactory);
User user = userDao.getUserById(10);
System.out.println(user);
}
@Test
public void testGetUserByName() {
UserDao userDao = new UserDaoImpl(sessionFactory);
List<User> list = userDao.getUserByName("张三");
System.out.println(list);
}
@Test
public void testInsertUser() {
UserDao userDao = new UserDaoImpl(sessionFactory);
User user = new User();
user.setUsername("武大郎");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("清河县");
userDao.insertUser(user);
}
}
存在的问题
- dao中操作数据库的代码重复。可以考虑使用模板替代。
- statementId存在硬编码的问题。
使用Mapper代理的方法开发dao
只写接口不写实现类
开发规范
1、mapper文件的命名规则推荐是“表名+Mapper.xml”。接口文件的名称和mapper映射文件的名称一致。
2、Mapper文件的namespace必须是接口的全限定名。
3、StatementID必须和接口中方法的名称一致。
4、接口的参数类型必须和parameterType一致。
5、接口的返回值类型必须和ResultType一致。
代码实现
Mapper文件:
<?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">
<!-- namespace的作用就是sql语句隔离.
如果使用Mapper代理形式开发,namespace必须是接口的全限定名-->
<mapper namespace="cn.mapper.UserMapper">
<!--
select:如果是一个select语句就需要使用select节点。
id就是一个sql语句的id,代表一个sql语句。起个名字叫做StatementId。
parameterType:参数的类型
resultType:返回结果的类型,可以是pojo类型,需要pojo的全限定名。
#{}:是一个占位符。相当于jdbc中的“?”,括号内容的名称,如果是简单数据类型可以随便起。
-->
<select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
SELECT * from user where id = #{id}
</select>
</mapper>
接口:
import cn.xx.pojo.User;
public interface UserMapper{
Uasr getUserById(int id);
}
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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 加载Mapper映射文件 -->
<mappers>
<!-- resource从classpath下开始查找 -->
<mapper resource="sqlmap/user.xml" />
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
测试方法
@Test
public void testGetUserById() {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(10);
System.out.println(user);
sqlSession.close();
}
@Test
public void testGetUserByName() {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserByName("张三");
System.out.println(list);
sqlSession.close();
}
Mapper代理形式是官方推荐的使用方法。也是企业开发中最常用的方法。
SqlMapConfig.xml
配置内容
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
注意:Mybatis的配置文件配置项是有顺序的,不能打乱。
Properties
<!-- 属性配置 -->
<!-- 可以使用resource加载外部配置文件 -->
<properties resource="db.properties">
<property name="JDBC_DRIVER" value="com.mysql.jdbc.Driver"/>
<property name="JDBV_URL" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="JDBC_USER" value="root"/>
<property name="JDBC_PASSWORD" value="root"/>
</properties>
如果同时使用的话,加载顺序是先加载内部的属性,然后再加载外部的属性。如果有重名的属性会覆盖。最终生效的是外部的属性文件。
Settings
Mybatis的全局属性配置
<settings>
<setting name="cacheEnabled" value="false"/>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
配置项参见
Setting(设置) | Description(描述) | Valid Values(验证值组) | Default(默认值) |
---|---|---|---|
cacheEnabled | 在全局范围内启用或禁用缓存配置任何映射器在此配置下。 | true | false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时,所有协会将热加载。 | true | false | TRUE |
aggressiveLazyLoading | 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 | true | false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 | true | false | TRUE |
useColumnLabel | 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true | false | TRUE |
useGeneratedKeys | 允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。 | true | false | FALSE |
autoMappingBehavior | 指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置驱动程序等待一个数据库响应的秒数。 | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许使用嵌套的语句RowBounds。 | true | false | FALSE |
mapUnderscoreToCamelCase | 从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。 | true | false | FALSE |
localCacheScope | MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。 | SESSION | STATEMENT | SESSION |
dbcTypeForNull | 指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定触发延迟加载的对象的方法。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定所使用的语言默认为动态SQL生成。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定如果setter方法或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 | true | false | FALSE |
logPrefix | 指定的前缀字串,MyBatis将会增加记录器的名称。 | Any String | Not set |
logImpl | 指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定代理工具,MyBatis将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST |
typeAliases
别名配置
Mybatis中定义的别名
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
自定义别名
<!-- 别名配置 -->
<typeAliases>
<!-- type:类的全限定名
alias:别名
别名不区分大小写
-->
<!-- <typeAlias type="cn.itcast.pojo.User" alias="user"/> -->
<!-- 可以使用package批量定义别名,name属性就是pojo类所在的包名的全限定名
别名就是类名,不区分大小写。
-->
<package name="cn.itcast.pojo"/>
</typeAliases>
Mappers
加载Mapper映射文件
<!-- 加载Mapper映射文件 -->
<mappers>
<!-- resource从classpath下开始查找 -->
<mapper resource="sqlmap/user.xml"/>
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
<!-- url配置的是文件的全路径 -->
<!-- <mapper url="file:///D:\传智播客\10.课堂笔记\0413\mybatis\day01\source\MybatisSecond0413\config\mapper\UserMapper.xml"/> -->
<!-- class指定接口的全限定名,要求Mapper映射文件和接口在同一个目录下,且名称相同。 -->
<!-- <mapper class="cn.itcast.mapper.UserMapper"/> -->
<!-- mapper接口所在包的全限定名,mybatis会扫描包下的接口,加载和接口同名的mapper映射文件 -->
<package name="cn.itcast.mapper"/>
</mappers>
Mapper映射文件
输入参数映射
基础数据类型
Integer、String、float等
POJO类型参数
例如添加用户、修改用户时使用user对象作为参数
POJO的包装类型
POJO中有一个属性,类型是POJO。
使用场合:查询条件复杂的时候,可以使用POJO的包装类型
QueryVo
|-user
|-item
创建一个QueryVo
package cn.itcast.pojo;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
使用QueryVo查询
需求:根据用户id查询用户信息
QueryVo
|-User
|-id
Sql语句:select * from user where id=1
Mapper文件:
<select id="getUserByQueryVo" parameterType="QueryVo" resultType="user">
<!-- 取属性名称使用“.”的方式来取 -->
select * from user where id=#{user.id}
</select>
接口定义:
public interface UserMapper{
User getUserByQueryVo(User user);
}
测试方法:
@Test
public void testGetUserByQueryVo() {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建一个QueryVo对象
QueryVo queryVo = new QueryVo();
//创建一个user对象
User user = new User();
user.setId(10);
queryVo.setUser(user);
User userResult = userMapper.getUserByQueryVo(queryVo);
System.out.println(userResult);
sqlSession.close();
}
Map类型
使用map作为参数进行映射。Map是key-value形式。绑定的时候应该使用#{key}。
返回值映射
返回基础数据类型
返回值是一个int或者String
Sql语句
select count(*) from user
Mapper 文件
<!-- 查询用户数量 -->
<select id="getUserCount" resultType="int">
select count(*) from user
</select>
方法定义
public interface UserMapper {
int getUserCount();
}
测试方法
@Test
public void testGetUserCount() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int count = userMapper.getUserCount();
System.out.println(count);
sqlSession.close();
}
要求sql语句的查询结果必须是一条记录,可以是多个列,多个列的情况下只取第一列的内容返回。
POJO类型的返回结果
根据用户id查询用户信息。返回一个user对象就是一个pojo。
POJO的List结果
根据用户名查询用户信息返回一个用户列表就是一个pojoList。
返回一个Map类型
Pojo要求返回的结果中列名和pojo的属性名要一致。
如果返回结果是map类型,那么key就是列名,value就是就是此列的值。
Pojo属性名和列名不一致
- 修改sql语句,使用别名保证结果集中的列名和pojo的属性名一致。
- 使用ResultMap
ResultMap入门
resultMap定义
<!-- resultMap的定义 -->
<!-- type:接收返回结果的数据类型,此处为user -->
<resultMap type="user" id="userResultMap">
<!--
id:为主键列
column:结果集中的主键列的列名
property:对应user对象中保存主键属性。
-->
<id column="id" property="id"/>
<!-- 普通列 -->
<result column="uname" property="username"/>
<result column="bday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="addr" property="address"/>
</resultMap>
<!-- resultMap属性指定一个resultMap的id -->
<select id="getUserResultMap" resultMap="userResultMap">
select id, username uname, birthday bday, sex, address addr from user
</select>
接口定义
public interface UserMapper{
List<User> getUserResultMap();
}
测试方法
@Test
public void testGetUserResultMap() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserResultMap();
System.out.println(list);
sqlSession.close();
}
动态sql
If
需求:根据参数的不同调整查询条件
Mapper文件
<select id="getUserList" parameterType="user" resultType="user">
select * from user
where 0=0
<if test="id!=null and id != 0">
and id = #{id}
</if>
<if test="username != null and username != '' ">
and username like '%${username}%'
</if>
</select>
接口定义
public interface UserMapper{
List<User> getUserList(User user);
}
测试方法
@Test
public void testGetUserList() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建user对象作为查询条件
User user = new User();
user.setId(1);
user.setUsername("张三");
List<User> userList = userMapper.getUserList(user);
System.out.println(userList);
sqlSession.close();
}
Where
可以根据条件动态的添加where关键字,并且可以去掉多余的and
<select id="geUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id != null and id != 0">
and id = #{id}
</if>
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
</where>
</select>
Foreach
创建QueryVo对象
public class QueryVo {
private User user;
private int[] ids;
//省略get和set方法
}
Mapper文件
<select id="getUserList" parameterType="QueryVo" resultType="user">
select * from user
<where>
<if test="user!=null">
<if test="user.id!=null and user.id != 0">
and id = #{user.id}
</if>
<if test="user.username != null and user.username != '' ">
and username like '%${user.username}%'
</if>
</if>
<if test="ids!=null">
<!--
collection:QueryVo中的集合属性ids
open:前缀
close:后缀
item:循环的变量名称
separator:分隔符
-->
<foreach collection="ids" open="and id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
接口定义
public interface UserMapper{
List<User> getUserList(QueryVo queryVo);
}
测试方法
@Test
public void testGetUserList() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建user对象作为查询条件
User user = new User();
//user.setId(1);
//user.setUsername("张三");
QueryVo queryVo = new QueryVo();
queryVo.setUser(user);
int[] ids = {1,10,16,22,24};
queryVo.setIds(ids);
List<User> userList = userMapper.getUserList(queryVo);
System.out.println(userList);
sqlSession.close();
}