mybatis 框架
概述
mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程
面试题: mybatis是基于ORM思想的半自动持久层框架- ORM对象关系映射:让实体类与表产生映射关系,操作实体类等同于操作表
开发步骤
- 创建maven仓库工程,添加依赖
- 编写实体类
- 编写映射配置文件(同包同名)
- 编写核心配置文件
- 编写测试类
- 加载配置文件
- 创建sqlSessionFactory
- 创建sqlSession
- sqlSession调用方法
-
释放资源,
核心配置文件中的标签设置
所有标签,且按照配置标签既定的顺序排列
properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?
1. properties标签 : 加载外部properties配置文件 resource
两个属性:
- resource属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下resource="jdbcConfig.properties"
-
url属性: 统一资源定位符
http://localhost:8080/mystroe/CategoryServlet
2. typeAliases标签: 自定义别名
两种定义: - 单个别名定义
<typeAlias alias="user" type="com.itheima.domain.User"/>
-
批量别名定义,扫描整个包下的类,别名为类名(首字母大写或者小写都可以)
<package name="com.itheima.domain"/>
3. environments标签: 数据库环境的配置,支持多环境配置
<!--.数据源环境-->
<environments default="development">
<environment id="development">
<!--事物类型 jdbc -->
<transactionManager type="JDBC"></transactionManager>
<!--使用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>
<environments default="development">
指定默认的环境名称<environments id="development">
指定当前环境的名称<transactionManager type="JDBC">
指定事务管理类型是jdbc<dataSource type="POOLED">
指定当前数据源类型是连接池<proprety name= value=>
数据源配置的基本参数
事物管理器(transactionManager)类型,两种
- JDBC: 这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事物作用域
-
managed: 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
数据源(dataSource)类型, 三种 - unpooled: 这个数据源的实现只是每次被请求时打开和关闭连接。
- POOLED: 实现利用“池”的概念将 JDBC 连接对象组织起来。
-
JNDI: 实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
4. mapper标签: 映射器,作用:加载映射
- 方式一: 使用相对于类路径的资源引用
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
- 方式二: 使用完全限定资源定位符(URL)
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
- 方式三: 使用映射器接口实现类的完全限定类名
<mapper class="org.mybatis.builder.AuthorMapper"/>
方式四: 将包内的映射器接口实现全部注册为映射器,只能在mapper代理开发中使用,相当于扫包,指定包下的所有实现类. 常用的方式
<package name="org.mybatis.builder"/>
MyBatis相应API介绍sqlSession
1.sqlSession工厂构建器(构建者模式)SqlSessionFactory build(InputSream inputStream)
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
//String resource = "org/mybatis/builder/mybatis-congfig.xml";
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//构建者设计模式
SqlSessionFactory factory = builder.build(inputStream);
2.sqlSession工厂对象(工厂模式)
工厂的作用就是造 sqlSession 会话对象. 工厂模式就是为了解耦和
SqlSessionFactory 有多个个方法创建SqlSession 实例。常用的有如下两个:
|方法|解释|
|:------:|:------------|
|openSession|会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交该事务,更新操作数据才会持久化到数据库中|
|openSession(boolean autoCommit)|参数为是否自动提交,true(自动提交)|
3.sqlSession会话对象(重要)
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
SqlSession sqlSession = sqlSessionFactory.openSession(true);
- 执行sql语句方法:
//查询
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
//增 删 改
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
- 操作事务的方法:
void commit()
void rollback()
mapper代理方式
1.Mybatis的Dao层实现有两种方式:
1-传统开发方式: 手动对Dao层进行实现,在Dao层编写接口,接口实现类,实现方法
2-代理开发方式: 编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
2.mapper代理开发要求(规范):
mapper接口开发需要遵循规范 | 示例 |
---|---|
1-接口和映射文件要同包同名 | java.cn.ppvir.dao.UserMapper.java和resources/cn/ppvir/dao/UserMapper.xml |
2-持久层映射配置中mapper标签的namespace属性取值必须是持久层接口的全限定类名 |
public interface Usermapper{} ---<mapper namespace=‘cn.ppvir.dao.UserMapper‘>
|
3-sql语句的配置标签<select><insert><delete><update> 的id属性必须和持久层接口的方法名相同 |
User findById(Int id) ---<select id="findById">
|
4-parameterType要和接口中的传入参数类型相同 |
User findById(int id) ---<select parameterType="int">
|
5-resultType要和接口中的返回值结果类型相同 |
User findById(int id) ---<select resultType="user">
|
3.代码演示(使用mapper代理开发)
模糊查询中${} 和 #{}的区别
#{}表示一个占位符
#{}可以实现prepareStatment向占位符中设置值,自动进行JDBC和java类型转换,防止sql注入
#{}可以接收简单类型值或pojo属性值,如果parameterType传输基本数据类型,值随便写
${}表示拼接sql串
${}是将传入的参数原样拼接在sql中,不进行jdbc类型转换
${}可以接收简单类型值或pojo属性值,如果parameterType传输基本数据类型,${}括号中只能是value
- pom
- 核心配置文件 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>
<!--1.引入配置文件-->
<properties resource="jdbc.properties"/>
<!--2.别名typeAliases-->
<typeAliases>
<!--单个别名定义-->
<typeAlias type="it.ppvir.domain.User" alias="user"></typeAlias>
<!--批量别名定义-->
<package name="it.ppvir.domain"/>
</typeAliases>
<!--3.数据源环境-->
<environments default="develop">
<environment id="develop">
<transactionManager type="JDBC"></transactionManager>
<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>
<!--4.加载映射文件-->
<mappers>
<!--方式一: 使用相对于类路径的资源引用-->
<mapper resource="it/ppvir/dao/UserMapper.xml"/>
<!--方式四:将包内的映射器接口实现全部注册为映射器-->
<!--<package name="it.ppvir.dao"/>-->
</mappers>
</configuration>
- 实体类 get set toString
public class User {
private int id;
private String username;
private String password;
- 映射配置文件 UserMapper.xml resources/it/ppvir/dao/Usermapper.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="it.ppvir.dao.UserMapper">
<!--查询所有 List<User> findAll();-->
<select id="findAll" resultType="user">
select * from users;
</select>
<!--通过id 查询用户User findUserById(int id);-->
<select id="findUserById" parameterType="int" resultType="user">
select * from users where id=#{id}
</select>
<!--添加user void addUser(User user);-->
<insert id="addUser" parameterType="user">
<!--keyProperty:将添加成功后的id值查询出来封装到那个实体属性上
resultType:主键类型
order:SELECT LAST_INSERT_ID()执行时机是在insert后面-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into users VALUES (#{id},#{username},#{password})
</insert>
<!--删除用户 void delUserById(int id);-->
<delete id="delUserById" parameterType="int">
DELETE FROM users where id=#{id}
</delete>
<!--修改用户信息 void modUserById(int id);-->
<update id="modUserById" parameterType="user">
UPDATE users SET username=#{username} where id=#{id}
</update>
<!--模糊查询 List<User> findUserByLikeUsername(String username);-->
<select id="findUserByLikeUsername" resultType="user" parameterType="String">
select * from users where username like '${value}'
</select>
</mapper>
- 接口 接口和映射同包同名 方法名和id值相同 返回值和resultType相同 形参和ParameterType相同
public interface UserMapper {
//插入数据 addUser
void addUser(User user);
//查询所有用户 findAll
List<User> findAll() throws IOException;
//查询用户通过id findUserById
User findUserById(int id);
//通过Id删除用户 delUserById
void delUserById(int id);
//通过id修改用户信息 modUserById
void modUserById(User user);
//模糊查询
List<User> findUserByLikeUsername(String username);
}
- 测试类
public class UserMapperTest {
/**
* 接口实现类测试 传统方法
* @throws IOException
*/
@Test
public void test01() throws IOException {
UserMapper userMapper = new UserMapperImpl();
List<User> users = userMapper.findAll();
System.out.println(users);
}
/**
* mapper代理方式 实现findAll方法
*/
@Test
public void test02() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
//使用mapper代理方式
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//通过接口获取mapper代理对象
List<User> users = mapper.findAll();//使用代理对象调用接口的方法
System.out.println(users);
}
@Test
/**
* mapper代理方式 实现 User findUserById(int id)
*/
public void test03() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//mapper代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findUserById(19);
System.out.println(user);
}
@Test
/**
* mapper代理方式 添加用户void addUser(User user); 并且获取到添加后user 的id
*/
public void test04() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//封装实体类
User user = new User();
user.setUsername("euuruqwo");
user.setPassword("123123");
System.out.println("添加前"+user);
//mapper代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.addUser(user);
sqlSession.commit();
System.out.println("添加后"+user);
}
@Test
/**
* mapper代理方式 删除用户
*/
public void test05() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//mapper代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.delUserById(25);
}
@Test
/**
* mapper代理方式 修改用户
*/
public void test06() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//封装实体类
User user = new User();
user.setId(2);
user.setUsername("2222222");
//mapper代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.modUserById(user);
}
//模糊查询测试
@Test
public void queryLike() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
//mapper代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findUserByLikeUsername("%张%");
for (User user : users) {
System.out.println(user);
}
}
}