Mybatis第一课-牛
2017-07-12 16:24
169 查看
Mybatis第一天
1 课程计划
JAVAEE开发的三剑客:三大框架SSM
Mybatis:封装jdbc访问代码的一个框架 (hibernate) ORM
Spring MVC:用来封装servlet编程的一个框架(struts2)
Spring:体系整合框架,其他框架的粘合剂;
什么是框架:
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种定义认为,框架是可被应用开发者定制的应用骨架。是用框架可以提高程序复用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。
框架的优点(总结)
1.灵活可配置:将程序中写死的代码(硬编码)可以写到配置文件中
解耦
2.代码复用性高:将程序中反复要写的代码(套路代码)进行抽取封装,提高代码的复用性
3.简化开发:框架将底层复杂的细节进行了封装,并提供了方便调用的API,使得开发人员将工作的重点转移到实际业务中,大大提高了项目的开发效率
第一天:
1、mybatis的介绍
2、Mybatis的入门
a) 使用jdbc操作数据库存在的问题
b) Mybatis的架构
c) Mybatis的入门程序
3、Mybatis的开发流程
4、dao开发
实现增删改查
第二天:
1、抽取DAO接口
2、通过反射动态加载类
3、Mapper动态代理
第三天:
1、输出映射
2、动态sql
3、设计表及表关系的存储
本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
eclipse mars
Jdk:1.7
1、创建一个java工程。
2、导入jar包。此时需要mysql
的数据库驱动。
2、 创建并获取数据库链接
3、 创建jdbc statement对象
4、 设置sql语句
5、 设置sql语句中的参数(使用preparedStatement)
6、 通过statement执行sql并获取结果
7、 对sql执行结果进行解析处理
8、 释放资源(resultSet、preparedstatement、connection)
args) {
Connection connection = null;
PreparedStatement preparedStatement =
null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
"root",
"root");
//定义sql语句 ?表示占位符
String sql =
"select * from user where username
= ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1,
"王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上边使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作。
2、 Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
3、 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
补充:持久层框架总结
Jdbc,DBUtil,Hibernate,Mybatis等
mybatis解决了前面这些框架的痛点,来说一下痛点
jdbc:
优点:原生,速度快
缺点:使用不方面,先得get再set
DBUtils:
优点:只要数据库名字和实体类名字,一致,就自动设置属性,底层用的反射
缺点:sql语句写在类中,改sql就得改代码,硬编码
Hibernate
优点:hql语句,需要把sql写到文件里面,提供了一种对象关系映射,用起来更方便
缺点:底层运行的效率不太高
mybatis就解决了前面的所有问题
优点简述:
在原生api的基础上,进行的进一步封装,开发使用起来,更方便,效率更高。
隐藏了底层复杂的实现过程,使得不用关注底层,只需关注业务逻辑的开发。
通过使用配置文件或者注解的方式,使应用程序更加的灵活。
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂(单例)
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped
Statement对象,sql的id即是Mapped
statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
mybatis-3.2.7.jar----mybatis的核心包
lib----mybatis的依赖包
mybatis-3.2.7.pdf----mybatis使用手册
根据用户id查询一个用户信息
查询所有用户
添加用户
更新用户
删除用户
<?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/ssm?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
Public class User {
private Long
id;
private String
name;//
用户姓名
private int age;//
年龄
get/set……
<?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="User">
<select id="findAll" resultType="cn.edu360.mybatis.day1.User">
</select>
</mapper>
namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。
<!--
核心配置文件可以组装我们的mapper映射文件 -->
<mappers>
<mapper resource="UserMapper.xml" />
</mappers>
public static void main(String[]
args) throws IOException {
// 配置文件(1,核心配置文件,用于组装映射配置文件,2映射配置文件,用于实体类和数据库表的对应关系)
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// sqlSessionFactory
工厂,产生sqlSession
// sqlSessionFactory
相当于jdbc中的DriverManager
连接池
// sqlSession
相当于jdbc中的Connection对象
// sqlSessionFactoryBuilder
构建器
SqlSessionFactoryBuilder sqlSessionFactoryBuilder =
new SqlSessionFactoryBuilder();
// 通过构建器的build
方法 获取sqlSessionFactory
SqlSessionFactory sqlSessionFactory =
sqlSessionFactoryBuilder.build(in);
// 通过sqlSessionFactory的openSession方法,获取到了一个sqlSession
SqlSession sqlSession = null;
try {
sqlSession =
sqlSessionFactory.openSession();
// 执行sql
List<User> list =
sqlSession.selectList("User.findAll");
for (User
u : list) {
System.out.println(u.getName());
}
} finally {
// 释放资源
if (sqlSession !=
null)
sqlSession.close();
}
}
}
1,创建project,导入jar包(驱动连接包,mybatis核心包,mybatis依赖包)
2,创建核心的配置文件sqlMapConfig.xml,设置一个JDBC的连接,然后修改我们的连接池配置(数据库驱动名,数据库的连接url,数据库用户名,数据库用户密码)
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
3,创建映射配置文件UserMapper.xml,mapper标签需要命名空间namespace唯一,我们可以再这个标签下面编写我们的增删改查sql语句
4,在核心配置文件里面,把编写好的映射配置文件添加进去,<mappers>(组装)
5,新建一个程序,调用sqlSessionFactoryBuilder的 build方法,获得一个sqlSessionFactory对象。
6,通过sqlSessionFactory的openSession()方法获取sqlSession
7,通过sqlSession执行我们的增删改查业务逻辑
8,解析查询数据
9,调用close方法关闭连接。
注意:这里是把连接返回给给连接池,不是真正的关闭连接。
mybatis开发优点总结:
1, sql语句和代码分离,解决了硬编码问题,实现了解耦
2, 使用mybatis自带的连接池,还可接入第三方连接池
3, 自动实现了数据库表字段和实体类属性的映射,使用方便
4, 封装了查询接口,隐藏了底层实现,使开发人员更专注于业务逻辑代码的开发
JUnit单元测试要求:
1, 方法必须是public
2, 返回值类型必须是void
3, 方法必须没有参数
4, 可以抛出异常,但是不主动捕获异常
5, 方法需要加上@Test注解
public class UserDao {
private static SqlSessionFactory
sqlSessionFactory = null;
// 在構造方法之前执行,在类加载的时候执行
static {
// 创建sqlSessionFactory
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
} catch (IOException
e) {
// 执行一些异常处理
// log.log(e)
e.printStackTrace();
}
}
}
<!--
添加用户 -->
<insert id="save1" parameterType="cn.edu360.mybatis.day1.User">
INSERT INTO t_user (id,name) VALUES (null,#{name})
</insert>
user){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// insert 方法 传递了一个user对象,这个user对象封装了用户数据
int count =
sqlSession.insert("User.save1",
user);
// 解析返回结果
System.out.println(count);
// 执行修改操作,必须提交事务 (save,udpate,delete)
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
public void testSave() {
// 调用dao里面的save方法
UserDao dao = new UserDao();
// 创建实体类
User u = new User();
// 赋值
u.setName("凤姐");
dao.save(u);
}
删除用户 -->
<delete id="deleteById" parameterType="long">
DELETE FROM t_user where id = #{id}
</delete>
id) {
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// insert 方法 传递了一个user对象,这个user对象封装了用户数据
int count =
sqlSession.delete("User.deleteById",
id);
// 解析返回结果
System.out.println(count);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
public void testDeleteById() {
// 创建dao
UserDao dao = new UserDao();
// 调用方法
dao.deleteById(14L);
}
UPDATE t_user SET name=#{name}, age = #{age} WHERE id = #{id}
</update>
user) {
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.update("User.update",
user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
dao = null;
@Before
public void init(){
dao = new UserDao();
}
@Test
public void testUdpate() {
// 创建实体对象
User u = new User();
// 赋值
u.setName("凤姐万人迷");
u.setAge(18);
u.setId(15L);
// 调用方法
dao.update(u);
}
自定义条件查询用户列表 -->
<select id="getById" parameterType="long"
resultType="cn.edu360.mybatis.day1.User">
select * from t_user where id = #{id}
</select>
id){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
User user =
sqlSession.selectOne("User.getById",
id);
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
public void testGetById(){
dao.getById(15L);
}
select * from t_user
</select>
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
List<User> user = sqlSession.selectList("User.findByName");
for(User
u:user){
System.out.println(u);
}
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
public void testFindAll(){
dao.FindAll();
}
SELECT * FROM t_user where name = #{name}
</select>
name){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
User user = sqlSession.selectOne("User.getByName",
name);
System.out.println("name="+user.getName());
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
public void testGetByName(){
dao.getByName(“凤姐”);
}
SELECT * FROM t_user WHERE name like '%${value}%'
</select>
parameterType:定义输入到sql中的映射类型,${value}表示使用参数将${value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。
模糊匹配如果写name like #{name} ,
需要在测试代码里面进行模糊匹配,否则和name = #{name}
查询结果一样
List<User> uList = dao.findByName("%凤姐%");
配置文件中还可以写成:
SELECT * FROM t_user where name like "%"#{name}"%"
name){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
List<User> user = sqlSession.selectList("User.findByName",
name);
System.out.println("name="+user.size());
// 释放资源
sqlSession.close();
// 返回查询结果
return null;
}
public void testFindByName(){
dao.FindByName(“凤姐”);
}
如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType
传入的内容拼接在sql中且不进行jdbc类型转换,
${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录映射为resultType指定类型的对象。
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。
解决:在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定义输出结果的类型。
通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到
finally 块中以确保每次都能执行关闭。如下:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
补充: DTD约束的本地文件加载配置
1、在eclipse中点击
2、
3、添加dtd约束文件
1 课程计划
JAVAEE开发的三剑客:三大框架SSM
Mybatis:封装jdbc访问代码的一个框架 (hibernate) ORM
Spring MVC:用来封装servlet编程的一个框架(struts2)
Spring:体系整合框架,其他框架的粘合剂;
什么是框架:
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种定义认为,框架是可被应用开发者定制的应用骨架。是用框架可以提高程序复用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。
框架的优点(总结)
1.灵活可配置:将程序中写死的代码(硬编码)可以写到配置文件中
解耦
2.代码复用性高:将程序中反复要写的代码(套路代码)进行抽取封装,提高代码的复用性
3.简化开发:框架将底层复杂的细节进行了封装,并提供了方便调用的API,使得开发人员将工作的重点转移到实际业务中,大大提高了项目的开发效率
第一天:
1、mybatis的介绍
2、Mybatis的入门
a) 使用jdbc操作数据库存在的问题
b) Mybatis的架构
c) Mybatis的入门程序
3、Mybatis的开发流程
4、dao开发
实现增删改查
第二天:
1、抽取DAO接口
2、通过反射动态加载类
3、Mapper动态代理
第三天:
1、输出映射
2、动态sql
3、设计表及表关系的存储
2 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对象并返回。
3 使用jdbc编程问题总结
3.1 创建mysql数据库
先导入创建数据库的sql脚本导入到数据库中。3.2 创建工程
开发环境:eclipse mars
Jdk:1.7
1、创建一个java工程。
2、导入jar包。此时需要mysql
的数据库驱动。
3.3 jdbc编程步骤:
1、 加载数据库驱动2、 创建并获取数据库链接
3、 创建jdbc statement对象
4、 设置sql语句
5、 设置sql语句中的参数(使用preparedStatement)
6、 通过statement执行sql并获取结果
7、 对sql执行结果进行解析处理
8、 释放资源(resultSet、preparedstatement、connection)
3.4 jdbc程序
public static void main(String[]args) {
Connection connection = null;
PreparedStatement preparedStatement =
null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
"root",
"root");
//定义sql语句 ?表示占位符
String sql =
"select * from user where username
= ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1,
"王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上边使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作。
3.5 jdbc问题总结如下:
1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。2、 Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
3、 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
补充:持久层框架总结
Jdbc,DBUtil,Hibernate,Mybatis等
mybatis解决了前面这些框架的痛点,来说一下痛点
jdbc:
优点:原生,速度快
缺点:使用不方面,先得get再set
DBUtils:
优点:只要数据库名字和实体类名字,一致,就自动设置属性,底层用的反射
缺点:sql语句写在类中,改sql就得改代码,硬编码
Hibernate
优点:hql语句,需要把sql写到文件里面,提供了一种对象关系映射,用起来更方便
缺点:底层运行的效率不太高
mybatis就解决了前面的所有问题
优点简述:
在原生api的基础上,进行的进一步封装,开发使用起来,更方便,效率更高。
隐藏了底层复杂的实现过程,使得不用关注底层,只需关注业务逻辑的开发。
通过使用配置文件或者注解的方式,使应用程序更加的灵活。
4 Mybatis架构
5 Mybatis流程图
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂(单例)
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped
Statement对象,sql的id即是Mapped
statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
6 Mybatis入门程序
6.1 mybatis下载
mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releasesmybatis-3.2.7.jar----mybatis的核心包
lib----mybatis的依赖包
mybatis-3.2.7.pdf----mybatis使用手册
6.2 需求
实现以下功能:根据用户id查询一个用户信息
查询所有用户
添加用户
更新用户
删除用户
6.3 工程搭建
6.3.1 第一步:创建java工程
使用eclipse创建java工程,jdk使用1.8。6.3.2 第二步:加入jar包
加入mybatis核心包、依赖包、数据驱动包。6.3.3 第三步: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/ssm?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
6.3.4 第四步:实体类
实体类作为mybatis进行sql映射使用,实体类通常与数据库表对应,User.java如下:Public class User {
private Long
id;
private String
name;//
用户姓名
private int age;//
年龄
get/set……
6.3.5 第五步:sql映射文件
在classpath下的sqlmap目录下创建sql映射文件User.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="User">
<select id="findAll" resultType="cn.edu360.mybatis.day1.User">
</select>
</mapper>
namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。
6.3.6 第七步:在核心配置文件中加载sql映射文件
mybatis框架需要加载映射文件,将User.xml添加在SqlMapConfig.xml,如下:<!--
核心配置文件可以组装我们的mapper映射文件 -->
<mappers>
<mapper resource="UserMapper.xml" />
</mappers>
6.3.7 执行测试
public class HelloWorld {public static void main(String[]
args) throws IOException {
// 配置文件(1,核心配置文件,用于组装映射配置文件,2映射配置文件,用于实体类和数据库表的对应关系)
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// sqlSessionFactory
工厂,产生sqlSession
// sqlSessionFactory
相当于jdbc中的DriverManager
连接池
// sqlSession
相当于jdbc中的Connection对象
// sqlSessionFactoryBuilder
构建器
SqlSessionFactoryBuilder sqlSessionFactoryBuilder =
new SqlSessionFactoryBuilder();
// 通过构建器的build
方法 获取sqlSessionFactory
SqlSessionFactory sqlSessionFactory =
sqlSessionFactoryBuilder.build(in);
// 通过sqlSessionFactory的openSession方法,获取到了一个sqlSession
SqlSession sqlSession = null;
try {
sqlSession =
sqlSessionFactory.openSession();
// 执行sql
List<User> list =
sqlSession.selectList("User.findAll");
for (User
u : list) {
System.out.println(u.getName());
}
} finally {
// 释放资源
if (sqlSession !=
null)
sqlSession.close();
}
}
}
7 Mybatis开发流程
以小案例为示例,说明mybatis的开发流程1,创建project,导入jar包(驱动连接包,mybatis核心包,mybatis依赖包)
2,创建核心的配置文件sqlMapConfig.xml,设置一个JDBC的连接,然后修改我们的连接池配置(数据库驱动名,数据库的连接url,数据库用户名,数据库用户密码)
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
3,创建映射配置文件UserMapper.xml,mapper标签需要命名空间namespace唯一,我们可以再这个标签下面编写我们的增删改查sql语句
4,在核心配置文件里面,把编写好的映射配置文件添加进去,<mappers>(组装)
5,新建一个程序,调用sqlSessionFactoryBuilder的 build方法,获得一个sqlSessionFactory对象。
6,通过sqlSessionFactory的openSession()方法获取sqlSession
7,通过sqlSession执行我们的增删改查业务逻辑
8,解析查询数据
9,调用close方法关闭连接。
注意:这里是把连接返回给给连接池,不是真正的关闭连接。
mybatis开发优点总结:
1, sql语句和代码分离,解决了硬编码问题,实现了解耦
2, 使用mybatis自带的连接池,还可接入第三方连接池
3, 自动实现了数据库表字段和实体类属性的映射,使用方便
4, 封装了查询接口,隐藏了底层实现,使开发人员更专注于业务逻辑代码的开发
8 DAO开发
8.1 需求
实现增删改案例,使用JUnit单元测试对代码进行测试,并对套路代码进行封装。JUnit单元测试要求:
1, 方法必须是public
2, 返回值类型必须是void
3, 方法必须没有参数
4, 可以抛出异常,但是不主动捕获异常
5, 方法需要加上@Test注解
8.2 创建DAO类
创建DAO类,并加载sqlSessionFactorypublic class UserDao {
private static SqlSessionFactory
sqlSessionFactory = null;
// 在構造方法之前执行,在类加载的时候执行
static {
// 创建sqlSessionFactory
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
} catch (IOException
e) {
// 执行一些异常处理
// log.log(e)
e.printStackTrace();
}
}
}
8.3 添加用户
8.3.1 映射文件:
在SqlMapConfig.xml中添加:<!--
添加用户 -->
<insert id="save1" parameterType="cn.edu360.mybatis.day1.User">
INSERT INTO t_user (id,name) VALUES (null,#{name})
</insert>
8.3.2 业务逻辑:
public void save(Useruser){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// insert 方法 传递了一个user对象,这个user对象封装了用户数据
int count =
sqlSession.insert("User.save1",
user);
// 解析返回结果
System.out.println(count);
// 执行修改操作,必须提交事务 (save,udpate,delete)
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
8.3.3 测试方法:
@Testpublic void testSave() {
// 调用dao里面的save方法
UserDao dao = new UserDao();
// 创建实体类
User u = new User();
// 赋值
u.setName("凤姐");
dao.save(u);
}
8.4 删除用户
8.4.1 映射文件:
<!--删除用户 -->
<delete id="deleteById" parameterType="long">
DELETE FROM t_user where id = #{id}
</delete>
8.4.2 业务逻辑:
public void deleteById(Longid) {
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// insert 方法 传递了一个user对象,这个user对象封装了用户数据
int count =
sqlSession.delete("User.deleteById",
id);
// 解析返回结果
System.out.println(count);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
8.4.3 测试程序:
@Testpublic void testDeleteById() {
// 创建dao
UserDao dao = new UserDao();
// 调用方法
dao.deleteById(14L);
}
8.5 根据id修改用户信息
8.5.1 映射文件:
<update id="update" parameterType="cn.edu360.mybatis.day1.User">UPDATE t_user SET name=#{name}, age = #{age} WHERE id = #{id}
</update>
8.5.2 业务逻辑:
public void update(Useruser) {
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.update("User.update",
user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
8.5.3 测试程序:
private UserDaodao = null;
@Before
public void init(){
dao = new UserDao();
}
@Test
public void testUdpate() {
// 创建实体对象
User u = new User();
// 赋值
u.setName("凤姐万人迷");
u.setAge(18);
u.setId(15L);
// 调用方法
dao.update(u);
}
8.6 根据ID查询用户信息
8.6.1 映射文件:
<!--自定义条件查询用户列表 -->
<select id="getById" parameterType="long"
resultType="cn.edu360.mybatis.day1.User">
select * from t_user where id = #{id}
</select>
8.6.2 业务逻辑:
public User getById(Longid){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
User user =
sqlSession.selectOne("User.getById",
id);
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
8.6.3 测试程序:
@Testpublic void testGetById(){
dao.getById(15L);
}
8.7 查询所有用户信息
8.7.1 映射文件:
<select id="findAll" resultType="cn.edu360.mybatis.day1.User">select * from t_user
</select>
8.7.2 业务逻辑:
public List<User> findAll(){// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
List<User> user = sqlSession.selectList("User.findByName");
for(User
u:user){
System.out.println(u);
}
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
8.7.3 测试程序:
@Testpublic void testFindAll(){
dao.FindAll();
}
8.8 根据name查询一条用户信息
8.8.1 映射文件:
<select id="getByName" parameterType="String" resultType="cn.edu360.mybatis.day1.User">SELECT * FROM t_user where name = #{name}
</select>
8.8.2 业务逻辑:
public User getByName(Stringname){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
User user = sqlSession.selectOne("User.getByName",
name);
System.out.println("name="+user.getName());
// 释放资源
sqlSession.close();
// 返回查询结果
return user;
}
8.8.3 测试程序:
@Testpublic void testGetByName(){
dao.getByName(“凤姐”);
}
8.9 根据name模糊查询用户信息
8.9.1 映射文件:
<select id="findByName" parameterType="String" resultType="cn.edu360.mybatis.day1.User">SELECT * FROM t_user WHERE name like '%${value}%'
</select>
parameterType:定义输入到sql中的映射类型,${value}表示使用参数将${value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。
模糊匹配如果写name like #{name} ,
需要在测试代码里面进行模糊匹配,否则和name = #{name}
查询结果一样
List<User> uList = dao.findByName("%凤姐%");
配置文件中还可以写成:
SELECT * FROM t_user where name like "%"#{name}"%"
8.9.2 业务逻辑:
public User findByName(Stringname){
// 调用mybatis的api进行操作
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
List<User> user = sqlSession.selectList("User.findByName",
name);
System.out.println("name="+user.size());
// 释放资源
sqlSession.close();
// 返回查询结果
return null;
}
8.9.3 测试程序:
@Testpublic void testFindByName(){
dao.FindByName(“凤姐”);
}
8.10 小结
8.10.1 #{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType
传入的内容拼接在sql中且不进行jdbc类型转换,
${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
8.10.2 parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。resultType:指定输出结果类型,mybatis将sql查询结果的一行记录映射为resultType指定类型的对象。
8.10.3 selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。
8.11 Mybatis解决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定义输出结果的类型。
8.12 SqlSession的使用范围
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
8.12.1 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。8.12.2 SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。8.12.3 SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到
finally 块中以确保每次都能执行关闭。如下:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
9 SqlMapConfig.xml配置文件
9.1 配置内容
SqlMapConfig.xml中配置的内容和顺序如下:properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
补充: DTD约束的本地文件加载配置
1、在eclipse中点击
2、
3、添加dtd约束文件
相关文章推荐
- 学习mybatis 第一课
- Mybatis第一课
- MyBatis第一课:回忆JDBC
- MyBatis映射文件的resultMap如何做表关联
- mybatis传多参数的问题
- MyBatis之传入参数
- MyBatis Review——加载mappers映射文件的三种方式
- spring中@param和mybatis中@param使用区别
- 学习日记:java SSM框架(Spring+SpringMVC+MyBatis)
- mybatis+mysql如何批量执行多条语句
- Spring+Mybatis配置事务管理
- 跟阿铭学 第一课 安装Centos
- Springboot+MyBatis - 代码跑起来
- mybatis 学习笔记
- Go语言第一课:Helloworld
- MyBatis之ResultMap简介,关联对象
- maven项目使用mybatis-generator自动生成代码
- 详细讲解Maven插件MyBatis-Generator以及如何修改源码
- mybatis参数传递
- postgresql+mybatis返回值是数据库字段名