★ MyBatis官网: http://www.mybatis.org/mybatis-3/zh/index.html
★ 持久层就是持久化对象:DAO层+ 数据库
DAO层:data access object
持久化对象:PO( persistence object)
============【介绍】
【定义】
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO为数据库中的记录
※ (Plain Old Java Objects,普通老式 Java 对象)
【作用】
替代了jdbc的工作(建立连接、手动设置参数、关流、while()循环结果集rs 转换为 list)
底层封装的就是jdbc,对jdbc做了封装,mybatis默认提供了一个连接池。【我们只要做写SQL语句和传参】
※ 如果表中字段名和实体类的属性名相同mybatis框架会自动映射(获取该类的各种方法、构造函数等信息)
【扩展】
ibatis和mybatis是一样的,只是一个旧版本一个是新版本
Struts2和SpringMVC是一样的
★ Hibernate跟MyBatis功能是一样的,都是orm框架(对象关系映射)对象跟关系型数据库做映射
Hibernate:中大型项目(SQL、HQL语句、creteria查询)
MyBatis:中小型项目
★ ORM(Object Relational Mapping,对象关系映射)
● 编写程序的时候,以面向对象的方式处理数据
● 保存数据的时候,却以关系型数据库的方式存储
★ ORM解决方案包含下面四个部分
● 在持久化对象上执行基本的增、删、改、查操作
● 对持久化对象提供一种查询语言或者API
● 对象关系映射工具
● 提供与事务对象交互、执行检查、延迟加载以及其他优化功能
=========【框架】
框架技术
● 是一个应用程序的半成品
● 提供可重用的公共结构
● 按一定规则组织的一组组件
分析优势
● 不再考虑公共问题
● 专心在业务实现上
● 结构统一,易于学习、维护
● 新手也可以写出好程序
【SSM和SSH架构】
● SSM:Spring/SpingMVC/MyBatis
● SSH:Spring/Struts2/Hibernate
Spring/SpingMVC/Hibernate
=======【下载jar包】
1、CSDN博客网站上查
2、GitHub网站下载mybatis框架源码,再找到里面的jar包,里面各种相关的依赖包都有
3、远程仓库 maven repository 网站下载
4、maven下载工具
==============【mybatis框架搭建步骤】
1、新建项目(java、web项目都支持)
2、导包--mybatis的jar包、mysql-connection数据库连接包
3、建类 实体类 POJO类(plain old java object)
4、建表 插入数据
5、添加配置文件 mybatis-config.xml
配置数据库连接信息
添加映射文件路径
6、添加映射文件
SQL语句 + 映射关系(一般我们写的pojo实体类属性名和数据库表中的字段名是一样的,所以不用写)
7、测试
【问题】
1、自动映射
如果修改某个属性名导致和表中字段的属性不一致,会导致最后查到的结果中该字段的结果为null或编译报错
2、实例化对象
构造函数被mybatis框架调用。因为我们在映射文件中写SQL语句注明了返回的结果集类型是User
框架到处是反射
3、MySQL不支持自动提交。
需要我们自己手动提交。 与数据会话对象session调用commit()方法
例如:session.commit();
4、向表中插入数据
语法1:insert into 表名称 values (值1, 值2,…)
语法2:insert into table_name (列1, 列2,…) values (值1, 值2,…)
● 当设计的表中有自增的列的时候,使用语法1插入数据,报:
Column count doesn’t match value count at row 1 缺少列。
因为使用语法2就必须要写所有的列数据(包括自增列),但是这样又和表产生冲突了,所以不能使用语法2。
【补充的知识点】
《mybatis一级缓存二级缓存》:https://www.cnblogs.com/happyflyingpig/p/7739749.html
mybatis为了提高查询的效率,将查到的结果中常用数据放入一级缓存中,实现快速读取,而不会再次发送SQL到数据库
● 那么mybatis是跟什么判断这是常查的数据呢?
1 传入的statementId
2 查询时要求的结果集 中的结果范围
3 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql()
4 传递给java.sql.Statement要设置的参数值
如果以上条件都完全一样,那么就认为它们是完全相同的两次查询。
● 一级缓存是SqlSession级别的缓存 ● 二级缓存是mapper级别的缓存
● MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能==>(默认是不开启的)
配置database.properties
===============================
driver=com.mysql.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,并且字符集设置为utf-8
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
数据库建表
==================================
/*
Navicat MySQL Data Transfer
Source Server : test
Source Server Version : 80011
Source Host : localhost:3306
Source Database : smbms
Target Server Type : MYSQL
Target Server Version : 80011
File Encoding : 65001
Date: 2019-04-17 10:24:10
*/
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for smbms_user
-- ----------------------------
DROP TABLE
IF
EXISTS `smbms_user`;
CREATE TABLE `smbms_user` (
`id` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`userCode` VARCHAR ( 15 ) CHARACTER
SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户编码',
`userName` VARCHAR ( 15 ) CHARACTER
SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称',
`userPassword` VARCHAR ( 15 ) CHARACTER
SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码',
`gender` INT ( 10 ) DEFAULT NULL COMMENT '性别(1:女、 2:男)',
`birthday` date DEFAULT NULL COMMENT '出生日期',
`phone` VARCHAR ( 15 ) CHARACTER
SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '手机',
`address` VARCHAR ( 30 ) CHARACTER
SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',
`userRole` INT ( 10 ) DEFAULT NULL COMMENT '用户角色(取自角色表-角色id)',
`createdBy` BIGINT ( 20 ) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT ( 20 ) DEFAULT NULL COMMENT '更新者(userId)',
`modifyDate` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY ( `id` )
) ENGINE = INNODB AUTO_INCREMENT = 16 DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci;-- ----------------------------
-- Records of smbms_user
-- ----------------------------
INSERT INTO `smbms_user`
VALUES
( '1', 'admin', '系统管理员', '1234567', '1', '1983-10-10', '13688889999', '北京市海淀区成府路207号', '1', '1', '2013-03-21 16:52:07', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '2', 'liming', '李明', '0000000', '2', '1983-12-10', '13688884457', '北京市东城区前门东大街9号', '2', '1', '2018-03-21 16:52:07', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '5', 'hanlubiao', '韩路彪', '0000000', '2', '1984-06-05', '18567542321', '北京市朝阳区北辰中心12号', '2', '1', '2014-12-31 19:52:09', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '6', 'zhanghua', '张华', '0000000', '1', '1983-06-15', '13544561111', '北京市海淀区学院路61号', '3', '1', '2013-02-11 10:51:17', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '7', 'wangyang', '王洋', '0000000', '2', '1982-12-31', '13444561124', '北京市海淀区西二旗辉煌国际16层', '3', '1', '2014-06-11 19:09:07', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '8', 'zhaoyan', '赵燕', '0000000', '1', '1986-03-07', '18098764545', '北京市海淀区回龙观小区10号楼', '3', '1', '2016-04-21 13:54:07', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '10', 'sunlei', '孙磊', '0000000', '2', '1981-01-04', '13387676765', '北京市朝阳区管庄新月小区12楼', '3', '1', '2015-05-06 10:52:07', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '11', 'sunxing', '孙兴', '0000000', '2', '1978-03-12', '13367890900', '北京市朝阳区建国门南大街10号', '3', '1', '2016-11-09 16:51:17', NULL, NULL );
INSERT INTO `smbms_user`
VALUES
( '13', 'codess', 'hhhh', 'pwd', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
=============【XML 配置文件】============
XML 配置文件中包含了对 MyBatis 系统的核心设置
1、获取数据库连接实例的数据源(DataSource)
2、决定事务作用域和控制方式的事务管理器(TransactionManager)
<environment> 元素体中包含了事务管理和连接池的配置
<mappers> 元素体中包含一组映射器(mapper),这些映射器的 XML映射文件包含了 SQL代码和映射定义信息
例如:
<?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>
<!-- 引入database.properties文件 -->
<properties resource="database.properties" />
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/zhiyou/mapper/UserMapper.xml"/>
</mappers>
</configuration>
※ 注意 XML 头部的声明,它用来验证 XML 文档正确性
测试用的实体类User
=======================
public class User {
private Integer id; //id
private String userCode; //用户编码
private String userName; //用户名称
private String userPassword; //用户密码
private Integer gender; //性别
private Date birthday; //出生日期
private String phone; //电话
private String address; //地址
private Integer userRole; //用户角色
private Integer createdBy; //创建者
private Date creationDate; //创建时间
private Integer modifyBy; //更新者
private Date modifyDate; //更新时间
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getUserRole() {
return userRole;
}
public void setUserRole(Integer userRole) {
this.userRole = userRole;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
@Override
public String toString() {
return "User [id=" + id + ", userCode=" + userCode + ", userName=" + userName + ", userPassword=" + userPassword
+ ", gender=" + gender + ", birthday=" + birthday + ", phone=" + phone + ", address=" + address
+ ", userRole=" + userRole + ", createdBy=" + createdBy + ", creationDate=" + creationDate
+ ", modifyBy=" + modifyBy + ", modifyDate=" + modifyDate + "]";
}
}
mybatis的映射文件(增、删、改、查)
===================================
<?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,namespace的值习惯上设置成包名+sql映射文件名,
这样就能够保证namespace的值是唯一的
-->
<mapper namespace="com.zhiyou.mapper.UserMapper">
<!-- 查询 -->
<select id="getAll" resultType="com.zhiyou.pojo.User">
select * from smbms_user
</select>
<!-- 查询 -->
<select id="getUser" parameterType="int" resultType="com.zhiyou.pojo.User">
select * from smbms_user where id=#{id}
</select>
<!-- 删除 -->
<delete id="deluser" >
delete from smbms_user where id=#{id}
</delete>
<!-- 修改 -->
<update id="edituser" >
update smbms_user set userCode=#{userCode},userName=#{userName} where id=#{id}
</update>
<!-- 增加 -->
<insert id="insertuser" >
insert into smbms_user
(userCode,userName,userPassword,gender,birthday,phone,address,userRole,createdBy,creationDate,modifyBy,modifyDate)
values
(#{userCode},#{userName},#{userPassword},#{gender},#{birthday},#{phone},#{address},#{userRole},#{createdBy},#{creationDate},#{modifyBy},#{modifyDate})
<!--
因为表中的id是自增的,但是下面这种格式插入数据,就必须要写所有的列数据,又刚好跟自增的列id产生冲突了,
所以怎么写都报错,解决方法就是不用这种方法插入
-->
<!-- insert into smbms_user values(id=#{id},userCode=#{userCode},
userName=#{userName},userPassword=#{userPassword}gender=#{gender},birthday=#{birthday},phone=#{phone},address=#{address},userRole=#{userRole},
createdBy=#{createdBy},creationDate=#{creationDate},modifyBy=#{modifyBy},modifyDate=#{modifyDate}) -->
</insert>
</mapper>
<!--
在select标签中编写查询的SQL语句, 设置select标签的id属性为getUser,id属性值必须是唯一的,不能够重复
使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
resultType="com.zhiyou.pojo.User"就表示将查询结果封装成一个User类的对象返回User类就是users表所对应的实体类
-->
mybatis的Test测试类增、删、改、查的java代码
=======================================[
// mybatis的配置文件
String resource = "mybatis-config.xml";
// 1 获取mybatis-config.xml的输入流
InputStream is = Resources.getResourceAsStream(resource);
// 2 创建SqlSessionFactory对象,完成对配置文件的读取
// SqlSessionFactory跟hibernate的sessionFactory是一样的
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//根据配置文件创建sqlSessionFactory
// 3 打开跟数据库的一个会话
SqlSession session=factory.openSession();
/**
* 映射sql的标识字符串,
* com.zhiyou.mapping.userMapper是userMapper.xml文件中mapper标签的namespace属性的值,
* getUser是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
*/
【查询所有】
// 4 执行SQL语句
List<User> list=session.selectList("com.zhiyou.mapper.UserMapper.getAll");
System.out.println("list长度: " + list.size());
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getId()+" "+list.get(i).getUserCode()+" "+list.get(i).getUserName());
}
【根据id查】
// 4 执行SQL语句
User user = session.selectOne("com.zhiyou.mapper.UserMapper.getUser",12);
System.out.println(user);
【删除】
// 4 执行SQL语句
int i = session.delete("com.zhiyou.mapper.UserMapper.deluser",12);
if(i>0) {
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
session.commit();
session.close();
【修改】
// 创建user对象
User user = new User();
user.setUserCode("sunwukong");
user.setUserCode("孙悟空");
user.setId(12);
// 4 执行SQL语句
int i = session.update("com.zhiyou.mapper.UserMapper.edituser",user);
if(i>0) {
System.out.println("修改成功");
}else {
System.out.println("修改失败");
}
session.commit();
session.close();
【添加】
// 创建user对象
User user = new User();
// user.setId(3); // 因为数据库表中id是自增的,所以这里的id不设置
user.setUserCode("sunwukong");
user.setUserName("孙悟空");
user.setUserPassword("666666");
user.setGender(1);
// 设置生日为系统当前时间
Date date = new Date();
user.setBirthday(date);
/*
// 也可以这样--指定时间
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
String str1 = "1994-12-12";
Date date1 = sdf1.parse(str1);
user.setBirthday(date1);
*/
user.setPhone("18888888888");
user.setAddress("上海市崇明岛");
user.setUserRole(3);
user.setCreatedBy(1);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str2 = "1994-12-12 13:12:10";
Date date2 = sdf2.parse(str2);
user.setCreationDate(date2);
user.setModifyBy(1);
// 设置修改时间为系统当前时间
Date date3 = new Date();
user.setModifyDate(date3);
// 4 执行SQL语句
int i = session.update("com.zhiyou.mapper.UserMapper.insertuser",user);
if(i>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
session.commit();
session.close();