Mybatis学习总结:
背景介绍:
mybatis:前身ibatis,于2010年迁移到google code,并改名为Mybatis。最后在2013年11月迁移到gitbub(全球开源网站)。
Mybatis 的初步认知:
- Mybatis 是一个半自动的ORM持久成框架。apache下的顶级项目。
- Mybatis是JDBC的轻量级的封装,使用时程序员只需要注入sql语句,mybatis通过映射可以灵活生成满足数据库的sql语句。
解决了jdbc的一下几个问题:
- 1.jdbc创建和销毁数据库的连接耗资源过大
解决方法:mybatis框架内置连接池。
- 2.sql语句在javaWeb 项目中,修改sql语句需要修改java项目中的代码不利于维护。
-解决方法:mybatis采用配置文件注入sql语句,使sql语句与java代码分离。 -
- 使用jdbc查询对象时,够多的参数书写不方便。(每一个参数需要书写一个?占位符,并且还需要写一句对应的java语句)且不利于维护;
- 解决方法:Mybatis使用自动映射java对象至sql语句,通过statement的parameterType进行传参
- 4.jdbc查询时存在硬编码,当sql语句改变,系统解析是也发生变化,造成系统不利于维护。
解决方法:Mybatis使用自动sql语句至Java对象,通过statement的resultType进行传参
Mybatis的使用步骤:
-
- 导入所需要的jar包,配置SqlMapConfig.xml,写入数据库连接信息,类的别名以及映射关系等信息;
-
- 加载配置文件,获取SqlSessionFactory对象
- 3.获取SqlSession对象:调用Mapper.xml的sql语句(insert,update,delete,selectOne,selectLists)
- 4.释放资源
案例展示:Mybatis的DAO层的两种方式:
原始DAO层开发方式:
1.数据库创建数据表本案例使用如下数据表:
1).创建t_user数据表
CREATE TABLE `t_user` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(255) DEFAULT NULL,
`usex` varchar(255) DEFAULT NULL,
`uage` int(11) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
2). 插入5条数据:
INSERT INTO t_user VALUES ('1', '张三', '男', '25');
INSERT INTO t_user VALUES ('2', '李四', '男', '26');
INSERT INTO t_user VALUES ('3', '王五', '男', '27');
INSERT INTO t_user VALUES ('4', '赵六', '男', '30');
INSERT INTO t_user VALUES ('5', '小敏', '男', '25');
2.导入jar包,并配置SqlMapConfig.xml文件:
1.1}. 导入如下图所示jar包和log4j.properties
注:jar包说明:
- asm-4.2.jar
- cglib-3.1.jar
-1. 处理字节码的jar包
- mybatis-3.3.0.jar
- mybatis的核心jar包
- mysql-connector-java-5.1.12-bin.jar
- 2.连接数据库jdbcjar包
- jstl-1.2
- 3.标签jar包
- 4.其余jar为日志记录jar包,因为mybatis没有日志记录系统需要引用日记jar包完成打印。
1.2). log4j.properties配置信息:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2}.完善配置配置信息如下:
2.1)配置jdbc.properties,基本事项信息:
jdbc.driverName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.user=root
jdbc.pass=520
2.2)配置SqlMapConfig.xml文件:
(一).配置文件信息解读:
1)
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
写入约束文件:
注:约束标签中有DTD表示:该文件的标签的书写必须按照内部规定。
2).属性标签:properties 目的:为连接数据库提供基本四项的信息:
两种使用如下:
2.1).手动单个设置属性信息(在xml文件中)
设置一个名称为jdbc.user 值为 root的属性。
2.2).引入写好的properits文件信息中的信息
注:properties标签会先加载内部标签,再加载外部文件,名称一致时,会替换内容
解析如下:
当执行properties,先将已有的属性(即在xml中先配置的信息)记性加载,然后在加载xml外的文件即(jdbc.properties),如果加载外部信息的时候遇到相同的属性名,则先加载的内容会被覆盖。
2.3)typeAliases 别名标签 作用 :给自定义的类设置别名:
两种使用方法:
[1].通过包设置别名:
解读:将com.web.dto下的所有类都以类名为别名,可简化在mapper.xml中的传参和返回类型的书写。配置好的别名都是类的类名,别名不部分大小写。
[2].通过类设置别名:
解读:将com.web.dto下的User类起名为user;
2.4)environments 环境配置标签 作用用于配置连接数据库的信息(当使用spring框架的时候就可以不用再配置)
解读:
设置模式为:开发模式
使用的连接方式:jdbc
配置连接的信息
2.5)mapper映射
四种使用方式:
[1].使用Mapper.xml配置文件的路径:
[2].使用Mapper的接口类的路径:
[3]. 使用Mapper.xml和Mapper接口所在的包配置映射
[4]. 使用Mapper.xml在本机上的路径
3}.创将Mybatis工具类和实体类以及测试类
工具类:
/**
* 功能描述:加载文件信息,获取sqlSession
*
* @Author 落叶尘纷
* @Date 2019/8/13 10:22
* @Version 1.0
*/
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
InputStream in = null ;
try {
in = Resources.getResourceAsStream("sqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
public static void release(SqlSession sqlSession) {
sqlSession.close();
}
}
实体类
/**
* 功能描述:分装user用户实体类
*
* @Author 落叶尘纷
* @Date 2019/8/13 8:10
* @Version 1.0
*/
public class User {
private Integer uid;
private Integer uage;
private String uname;
private String usex;
public User() {
}
public User(Integer uid, Integer uage, String uname, String usex) {
this.uid = uid;
this.uage = uage;
this.uname = uname;
this.usex = usex;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", uage=" + uage +
", uname='" + uname + '\'' +
", usex='" + usex + '\'' +
'}';
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Integer getUage() {
return uage;
}
public void setUage(Integer uage) {
this.uage = uage;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUsex() {
return usex;
}
public void setUsex(String usex) {
this.usex = usex;
}
}
创建UserMapper 接口 和UserMapper.xml文件:
UserMapper.xml约束如下:
开始测试:(原生DAO方式调用)
1.)查询所有的记录信息
mapper接口中的方法:
List findAllUsers();
mapper.xml中的sql
测试类中的方法:
@Test
/**
* 查询所有记录
* */
public void showAllUsers(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
// 调用查询方法:查询所有的信息
List userList = session.selectList("com.web.mapper.UserMapper.findAllUsers");
// 循环打印信息
for (User user : userList) {
System.out.println(user);
}
// 关闭资源
session.close();
}
2.1)条件查询相关记录:查询姓张的用户
mapper接口中的方法:
List findUserLikeName( String name);
mapper.xml中的sql
测试类中的方法:
public void findUserLikeName(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
//设置传给的参数
String name = "张";
// 调用查询方法:查询所有的信息
List userList = session.selectList("com.web.mapper.UserMapper.findUserLikeName",name);
// 循环打印信息
for (User user : userList) {
System.out.println(user);
}
// 关闭资源
session.close();
}
2.2)通过姓名查询记录
mapper接口中的方法:
1.List findUserByName(@Param("name") String name);
取值方式可以是#{name}
2. List findUserByName( String name);
取值方式只能是#{value}
mapper.xml中的sql
1.
2.
测试类中的方法:
@Test
public void findUserByName(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
//设置传给的参数
String name = "王五";
// 调用查询方法:查询所有的信息
User u = session.selectOne("com.web.mapper.UserMapper.findUserByName",name);
// 打印信息
System.out.println(u);
// 关闭资源
session.close();
}
2.2)通过id查询记录
mapper接口中的方法:
User findUserByID( Integer uid);
mapper.xml中的sql
测试类中的方法:
@Test
public void findUserByID(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
//设置传给的参数
Integer uid = 2;
// 调用查询方法:查询所有的信息
User u = session.selectOne("com.web.mapper.UserMapper.findUserByID",uid);
// 打印信息
System.out.println(u);
// 关闭资源
session.close();
}
执行结果:
3)插入数据:
mapper接口中的方法:
void addUser(User user);
mapper.xml中的sql
1.
insert into t_user(
uname,
uage,
usex
)values (
#{uname},
#{uage},
#{usex}
)
2.在idea中插入的selectKey 会报错但是不影响执行
select LAST_INSERT_ID()
insert into t_user(
uname,
uage,
usex
)values (
#{uname},
#{uage},
#{usex}
)
测试类中的方法:
@Test
public void addUser(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
//设置传给的参数
User user = new User();
user.setUage(36);
user.setUname("石敢当");
user.setUsex("男");
// 调用添加方法并返回影响行数
int insert = session.insert("com.web.mapper.UserMapper.addUser", user);
//添加
session.commit();
// 打印信息
System.out.println(user);
// 关闭资源
session.close();
}
4)修改信息
mapper接口中的方法:
void updateUser(User user);
mapper.xml中的sql
update t_user set uname = #{uname},
uage = #{uage},usex = #{usex} where uid =#{uid}
测试类中的方法:
@Test
public void updateUser(){
//获取 sqlSession
SqlSession session = MybatisUtil.getSqlSession();
//设置传给的参数
User user = new User();
user.setUid(1);
user.setUage(36);
user.setUname("赵小花");
user.setUsex("男");
// 查询修改修改的记录的信息
User user1 = session.selectOne("com.web.mapper.UserMapper.findUserByID", 1);
System.out.println(user1);
// 调用修改方法并返回影响行数
session.update("com.web.mapper.UserMapper.updateUser", user);
session.commit();
// 打印信息
System.out.println(user);
// 关闭资源
session.close();
}
总结:
-
:用于非条件拼接sql语句 例如 name like '#{name}' 这种不可取。
-
- $:用于条件拼接sql语句 正常使用会报错 例如 name = ${name} 或 name = ${value}
- 3.当在mapper接口中的参数没有使用@Param("别名")设置别名时,对于String类型的数据只能使用#{value} 或者 ${value} ,当起了别名时只有#可以使用别名获取。但是#和$使用的时候还需要注意使用的情况是否拼接。
- 4.其余类型的参数如果是单个可直接使用其参数名获取。
- 5.如果是多个相同的参数类型,可以使用@Param("别名")设置别名。
- 6.当数据过多可以使用map集合,通过主键名获取值。
- 7.使用list集合只能自定义封装类或是起别名。
- 8.使用时注意mapper.xml中的id名称是唯一的,且方法和mapper中的接口对应。
- 9.原始的DAO和动态DAO单个框架使用增删改的时候都需要使用 session.commit() 提交到数据库。(在联合spring框架就不需要,因为他有很完善的事务管理机制)
动态DAO层开发方式:
(mapper中的方法和mapper.xml和原始的一样);
1).查询所有信息:
测试类中的测试方法:
@Test
public void showAllUsers1(){
// 获取SqlSession
SqlSession session = MybatisUtil.getSqlSession();
// 通过sqlsession 放射 获取Mapper接口
UserMapper mapper = session.getMapper(UserMapper.class);
// 调用接口中的方法
List allUsers = mapper.findAllUsers();
// 循环打印
for (User allUser : allUsers) {
System.out.println(allUser);
}
// 释放资源
session.close();
}
2).添加信息:
@Test
public void addUser1(){
// 获取SqlSession
SqlSession session = MybatisUtil.getSqlSession();
// 通过sqlsession 放射 获取Mapper接口
UserMapper mapper = session.getMapper(UserMapper.class);
//设置传给的参数
User user = new User();
user.setUage(37);
user.setUname("赵花");
user.setUsex("男");
// 调用添加方法
mapper.addUser(user);
// 事务提交到数据库
session.commit();
System.out.println(user);
session.close();
}
3).修改信息
@Test
public void addUser1(){
// 获取SqlSession
SqlSession session = MybatisUtil.getSqlSession();
// 通过sqlsession 放射 获取Mapper接口
UserMapper mapper = session.getMapper(UserMapper.class);
//设置传给的参数
User user = new User();
user.setUid(1);
user.setUage(37);
user.setUname("赵类");
user.setUsex("女");
// 调用添加方法
mapper.updateUser(user);
// 事务提交到数据库
session.commit();
System.out.println(user);
session.close();
}
- 1.动态DAO方法:使用sqlSession通过反射获取Mapper接口对象。增删改查的方法直接利用
动态sql语句:
1) if 标签:
如果判断正确,将if标签内的信息拼接进去。如下:
- 使用的String类型只有一个的时候如果是模糊,依旧不能使用
2.1)不报错:
2.2)报错:
2).总结:当只有一个String类型的参数时,使用动态sql语句取值,非拼接转态只能使用#{value},拼接只能使用${value}。对于非动态,没有拼接的可以使用别名。拼接的只能使用${value}获取值。
3)Where 标签:
相当于一个添加一个where 关键字:语句解释如下:
等同于 :
4).sql标签:动态标签中唯一一个和select 同级别的标签:
作用:通常书写一个常用的条件,一般使用引入
findAllUsers 方法查询所有的记录数据
select * from t_user;
正确格式sql语句
正确识别大于号和小于号:无法识别的原因是因为标签使用的就是大于号和小于号,容易结束整条标签语句。
5).forEach标签:(集合数据循环)
delete from t_user
uid in
${id}
相当于sql语句:
delete form t_user where uid in (1,2){小括号好内是集合中的数据}
解释:
- collection:list属性的别名
- item :循环中使用时的别名
- separator每次循环中间的拼接字符
- open:开始符号
- close:结束符号
list 类型使用:
- 在mapper接口中的list参数起一个别名
- 封装在另一个类中作为属性使用