文档版本 | 开发工具 | 测试平台 | 工程名字 | 日期 | 作者 | 备注 |
---|---|---|---|---|---|---|
V1.0 | 2016.06.26 | lutianfei | none |
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
SqlSession履行进程以下:
if (ExecutorType.BATCH == executorType) {
executor = newBatchExecutor(this, transaction);
} elseif (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor, autoCommit);
}
* 5、 SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
思路
dao接口
public class UserDaoImpl implements UserDao {
// 需要向dao实现类中注入SqlSessionFactory
// 这里通过构造方法注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
// 释放资源
sqlSession.close();
return user;
}
@Override
public List<User> findUserByName(String name) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("test.findUserByName", name);
// 释放资源
sqlSession.close();
return list;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//履行插入操作
sqlSession.insert("test.insertUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//履行插入操作
sqlSession.delete("test.deleteUser", id);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在履行testFindUserById之前履行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
// 创建UserDao的对象
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 调用UserDao的方法
User user = userDao.findUserById(1);
System.out.println(user);
}
}
程序员编写mapper接口需要遵守1些开发规范,这样Mybatis可以自动生成mapper接口实现类代理对象。
开发规范:
于mapper接口地址
User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
public interface UserMapper {
//用户信息综合查询
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
//用户信息综合查询总数
public int findUserCount(UserQueryVo userQueryVo) throws Exception;
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;
//根据用户名列查询用户列表
public List<User> findUserByName(String name)throws Exception;
//插入用户
public void insertUser(User user)throws Exception;
//删除用户
public void deleteUser(int id)throws Exception;
}
<!-- 加载 映照文件 -->
<mappers>
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
<!-- 批量加载mapper
指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载,遵守1些规范:需要将mapper接口类名和mapper.xml映照文件名称保持1致,且在1个目录中
上边规范的条件是:使用的是mapper代理方法
-->
<package name="cn.itcast.mybatis.mapper"/>
</mappers>
@Test
public void testFindUserById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user = userMapper.findUserById(1);
System.out.println(user);
}
需求:将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。
在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=mysql
<!-- 加载属性文件 -->
<properties resource="db.properties">
<!--properties中还可以配置1些属性名和属性值 -->
<!-- <property name="jdbc.driver" value=""/> -->
</properties>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<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>
</environment>
</environments>
因此,通过parameterType
传递的属性具有最高优先级,resource
或 url
加载的属性次之,最低优先级的是 properties
元素体内定义的属性。
建议:
需求
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 |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
单个别名定义
援用别名:
批量定义别名(经常使用)
<!-- 别名定义 -->
<typeAliases>
<!-- 针对单个别名定义
type:类型的路径
alias:别名
-->
<!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
-->
<package name="cn.itcast.mybatis.po"/>
</typeAliases>
类型处理器 | Java类型 | JDBC类型 |
---|---|---|
BooleanTypeHandler | Boolean,boolean | 任何兼容的布尔值 |
ByteTypeHandler | Byte,byte | 任何兼容的数字或字节类型 |
ShortTypeHandler | Short,short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer,int | 任何兼容的数字和整型 |
LongTypeHandler | Long,long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float,float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double,double | 任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或10进制小数类型 |
StringTypeHandler | String | CHAR和VARCHAR类型 |
ClobTypeHandler | String | CLOB和LONGVARCHAR类型 |
NStringTypeHandler | String | NVARCHAR和NCHAR类型 |
NClobTypeHandler | String | NCLOB类型 |
ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB和LONGVARBINARY类型 |
DateTypeHandler | Date(java.util) | TIMESTAMP类型 |
DateOnlyTypeHandler | Date(java.util) | DATE类型 |
TimeOnlyTypeHandler | Date(java.util) | TIME类型 |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP类型 |
SqlDateTypeHandler | Date(java.sql) | DATE类型 |
SqlTimeTypeHandler | Time(java.sql) | TIME类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。 |
<mapper resource=" " />
使用相对类路径的资源 <mapper resource="sqlmap/User.xml" />
使用完全限定路径<mapper url=" " />
<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
通过mapper接口加载单个mapper
<!-- 通过mapper接口加载单个映照文件需要遵守1些规范:mapper接口类名和mapper.xml映照文件名称必须保持1致,且在1个package目录中;并且要使用mapper代理方法-->
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
<package name="cn.itcast.mybatis.mapper"/>
需求:
定义包装类型pojo
mapper.java
测试代码
#
中 id 和 username是hashmap的key。<!-- 传递<u>hashmap</u>综合查询用户信息 -->
<select id="findUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id=#{id} and username like '%${username}%'
</select>
Public void testFindUserByHashmap()throws Exception{
//获得session
SqlSession session = sqlSessionFactory.openSession();
//获限mapper接口实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构造查询条件Hashmap对象
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", 1);
map.put("username", "管理员");
//传递Hashmap对象查询用户列表
List<User>list = userMapper.findUserByHashmap(map);
//关闭session
session.close();
}
使用resultType进行输出映照,只有查询出来的列名和pojo中的属性名1致,该列才可以映照成功。
输出简单类型
需求
Usermapper.xml
Usermapper.java
测试代码
小结
输出pojo对象和pojo列表
在mapper.java指定的方法返回值类型不1样:
List<Pojo>
生成的动态代理对象中是根据mapper方法的返回值类型肯定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用)
mybatis中使用resultMap完成高级输出结果映照。
resultMap使用方法
案例: 将下边的sql使用User完成映照
SELECT id id_,username username_ FROM USER WHERE id=#{value}
<!-- 定义resultMap
将SELECT id id_,username username_ FROM USER 和User类中的属性作1个映照关系
type:resultMap终究映照的java对象类型,可使用别名
id:对resultMap的唯1标识
-->
<resultMap type="user" id="userResultMap">
<!-- id表示查询结果集中唯1标识
column:查询出来的列名
property:type指定的pojo类型中的属性名
终究resultMap对column和property作1个映照关系 (对应关系)
-->
<id column="id_" property="id"/>
<!--
result:对普通名映照定义
column:查询出来的列名
property:type指定的pojo类型中的属性名
终究resultMap对column和property作1个映照关系 (对应关系)
-->
<result column="username_" property="username"/>
</resultMap>
<!-- 使用resultMap进行输出映照
resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_ FROM USER WHERE id=#{value}
</select>
mapper.java
测试
@Test
public void testFindUserByIdResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user = userMapper.findUserByIdResultMap(1);
System.out.println(user);
}
甚么是动态sql
需求
mapper.xml
需求
定义sql片断,在UserMapper.xml顶部
向sql传递数组或List,mybatis使用foreach解析
需求
//两种方法:
SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)
List<Integer>
ids传入多个id <sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
<if test="ids!=null">
<!-- 使用 foreach遍历传入ids
collection:指定输入 对象中集合属性
item:每一个遍历生成对象中
open:开始遍用时拼接的串
close:结束遍用时拼接的串
separator:遍历的两个对象中需要拼接的串
-->
<!-- 使用实现下边的sql拼接:
AND (id=1 OR id=10 OR id=16)
-->
<foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
<!-- 每一个遍历需要拼接的串 -->
id=#{user_id}
</foreach>
<!-- 实现 “ and id IN(1,10,16)”拼接 -->
<!-- <foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=",">
每一个遍历需要拼接的串
#{user_id}
</foreach> -->
</if>
</if>
</sql>
测试代码
在UserQueryVo中:
public class UserQueryVo {
//传入多个id
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
<!-- 实现 “ and id IN(1,10,16)”拼接 -->
<!-- <foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=",">
每一个遍历需要拼接的串
#{user_id}
</foreach> -->