Mybatis入门
什么是框架?
框架就是一个提供了可重用的公共结构的半成品。为构建新的应用程序提供便利,是可以拿来就用的工具,还提供了可重用的设计。
框架的优点
1)不用再考虑公共问题,框架已经做好了
2)可以专心于业务逻辑,保证核心业务逻辑的开发
3)结构统一,便于学习和维护
4)框架中集成了前人的经验,可以帮助新手写出稳定,性能优良而且结构优美的高质量程序。
当前主流框架
1.Struts
2.hibernate框架
3.spring 框架
什么是数据持有化
就是将内存中的数据模型转换成存储模型,以及将存储模型转换为内存中的数据模型统称。
MyBatis
mybatis是一个开源的数据持久层框架。主要思想是将程序中的大量SQL语句剥离出来,配置在文件中,实现SQL的灵活配置。
什么是ORM
对象/映射是一种数据持久化技术。他在对象模型和关系型数据库之间建立对应关系,并且提供一种机制,通过JavaBean对象去操作数据库表中的数控。
MyBatis
基于ORM,MYBatis在对象模型和关系数据库表之间建立了一座桥梁。通过Mybatis,可以建立SQL关系映射,便捷地实现数据存储,查询,更改和删除操作。
搭建Mybatis环境
①下载并导入需要的依赖③编写MyBatis核心部署文件——-
④创建实体类——-⑤创建DAO接口/mapper——-⑥创建SQL映射文件/mapper.xml——-
⑦编写测试类
MyBatis优点
①、与JDBC相比,减少50%以上的代码量
②、mybatis是简单的持久化框架,小巧简单易学
③、mybatis相当[灵活],不会对应用程序或者数据库的现有设计强加任何 影响,SQL写在XML里,从程序代码彻底分离,既降低耦合度,又便于 统一管理和优化,还可重用。
④、提供XML标签,支持编写动态SQL语句
⑤、提供映射标签,支持对象与数据库的ORM字段关系映射
Mybatis框架的缺点
①、SQL语句的【编写工作量较大】,对开发人员编写SQL语句的功底又一定要求
②、SQL语句依赖数据库,导致数据库【移植性差】,不能随意更换数据库
Mybatis框架适用场合
对性能要求很高的项目,或者需求变化较多的项目。
Mybatis的三个基本要素
1、核心接口和类,
2、Mybatis核心配置文件config.xml
3、SQL映射文件 UserMapper.xml
1.三层架构的关系
表现层(Spring MVC 框架) 用于展示数据
业务层 处理业务需求
持久层(Mybatis框架) 与数据库交互
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&77
2.持久层技术解决方案
1.JDBC技术 Connection+PreparedStatement+ResultSet,JDBC是一种规范
2.Spring的JDBCTemplate Spring中对JDBC的简单封装只是一种工具类
3.Apache的DBUtils 和Spring的JDBCTemplate很像,也是对JDBC的简单封装,只是一种工具类
4.mybatis是一种成熟的框架,简单灵活,代码和SQL语句解耦,基于ORM(对象关系模型),MYBatis在【对象模型】和【关系数据库表】之间建立了一座桥梁,大大提高开发效率.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&77
3你对框架的理解是什么?
我对 框架的理解是框架( Framework )是【构成】一类特定软件可复用设计的【一组】相互协作的【类】。
3.1框架是某种应用的【半成品】,是一组组件,你来选择这些组件完成自己的【系统】
3.2 别人【帮你】完成了一部分,你只需要写你自己【私有】的部分,封装了细节,开发者使用【极简】的方式实现开发,提高效率,节省资源.
3.3 框架是成熟的,不断【升级迭代】的软件
3.4 框架是软件开发中的一套解决方案,【不同】的框架解决不同的问题
总的来说,框架一般处在底层应用平台(J2EE)和高层业务逻辑之间的中间层.,经常解决技术整合的问题,以上就是我对框架的理解
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7
4.传统jdbc技术代码和框架进行比较的特点
代码存在的问题以及解决方案:
- 数据库连接,使用时就创建,不使用立即释放,对数据库进行[【频繁连接开启和关闭,造成数据库资源浪费】,影响数据库性能。
对策:使用【数据库连接池】管理数据库连接。
- 将【sql语句硬编码到java代码】中,如果sql语句修改,需要重新编译java代码,不利于【系统维护】。
对策:将sql语句配置在XML配置文件中,即使sql变化,不需要java代码进行重新编译。
- 向sql语句【传参麻烦,因为sql语句的where条件不一定,可能多也可能少,向preparedStatement中设置参数,对【占位符位置和设置参数值】需要一一对应,而且硬编码在java代码中,不利于系统维护。
对策:将sql语句及占位符和参数全部配置在XML中。
Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型
4.从resultSet中【遍历数据】时,存在硬编码,将获取的表字段进行硬编码,不利于系统维护。对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将【数据库记录封装成pojo对象解】析比较方便
对策:Mybatis自动将sql执行结果映射成java对象,通过statement的resultType定义输出结果的类型
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&77
5.谈谈你对orm的理解
ORM是对象关系模型的缩写, 对象/映射是一种数据持久化技术。他在对象模型和关系型数据库之间建立对应关系,并且提供一种机制,通过JavaBean对象去操作数据库表中的数控。
只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象【持久化】到数据库中。
当前ORM框架主要有五种:Hibernate(Nhibernate),iBATIS,mybatis,EclipseLink,JFinal
******************************************************************************************************************************8
【上机实操】Mybatis环境搭建步骤
1.创建Maven工程并导入坐标【pom文件】
2.创建dao包【mapper】下实体类User和UserDao接口【mapper.java/mappper.xml】
3.创建Mybatis的主配置【核心配置文件】文件mybatis-config.xml文件
4.创建Sql映射配置文件UserDao.xml文件【Mapper.xml】注意id的标签头选项有四种select,update,delete,insert
//在配置文件中只有查询有返回值resultType,
增删改只有parameterType参数类型;
修改时,因为修改的参数个数不确定,所以在userMapper.interface中直接传递user对象,在.xml文件中直接#{}属性就可以了
优化1.使用lombok,[首先file,setting,plguin搜索jar],在pom文件中添加依赖,在pojo中添加@Data,@NoArgs@NoArgs
2.使用别名[在核心配置文件中设置实体类包名直接使用持久化对象的包名,对应的映射是接口的实现。Xml],
3.使用日志[在D盘下建包logs,并存放log4j.properties日志配置文件,并把日志配置文件放到资源文件夹下面一份]
4.运用组件测试工具;使用快捷键Alt+shift+s,点击MapperUser(j接口名)右键,快速生产多个方法的测试类。
1-0数据库sql语句【预先建立smbmsdb数据库,并使用当前数据库】
DROP TABLE IF EXISTS user;
CREATE TABLE user (
id INT(11) NOT NULL AUTO_INCREMENT,
userName VARCHAR(20) NOT NULL COMMENT ‘用户名称’,
userRole INT(11) NOT NULL COMMENT ‘角色id’,
password INT(6) NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;
/*Data for the table user */
INSERT INTO user(id,userName,userRole,password) VALUES (3,‘admin’,1,123456),(4,‘李四’,2,0),(5,‘王五’,3,0),(6,‘赵丽颖’,2,0),(8,‘王老三’,2,0);
1-1src/main下的pojo/dao/utils
package cn.kgc.kade2020.tyl.pojo;/*
@author tangyingli
@create 2020/12/25-14:16
@version 1.0
用户实体类,数据库名和类名完全对应
*/
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data@AllArgsConstructor@NoArgsConstructor
public class User {
/**
*用户编号
*/
private Integer id;
/**
*用户名
*/
private String userName;
/**
*角色编号
*/
private Integer userRole;
/**
*用户密码
*/
private String password;
}
package cn.kgc.kade2020.tyl.mapper;/*
@author tangyingli
@create 2020/12/25-14:27
@version 1.0
用户的持久层
*/
import cn.kgc.kade2020.tyl.pojo.User;
import java.util.List;
public interface UserMapper {
/*1.查询所有*/
List<User> getAllUser();
/*2.根据id查询单个用户*/
User getUserById(Integer id);
/*3.模糊查询*/
List<User> getUserByName(String userName);
/*4.查询全部*/
Integer getTotalCount();
/*5.增加*/
Integer addUser(User user);
/*7修改*/
Integer upUser(User user);
/*6根据id删除*/
Integer delUser(Integer id);
}
package cn.kgc.kade2020.tyl.utils;/*
@author tangyingli
@create 2020/12/25-15:01
@version 1.0
*/
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class MybatisUtil {
private static String config = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFactory = null;//声明工厂对象
/*创建本地线程变量
* * 为每一个线程管理一个session对象
* 每一个线程有且仅有一个session对象;
* 每一个线程都会new一个线程变量,从而分配自己的session对象*/
private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<SqlSession>();
/*1.创建工厂实例,并返回工厂对象*/
static {
try{
InputStream inputStream= Resources.getResourceAsStream(config);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
/*2.创建session会话,并存储到本地线程中,返回session对象;*/
private static void newSession(){
//打开一个session会话,并存储在本地线程变量中[会话工厂对象打开会话]
//打開session,參數設置為true,增刪改自動提交;
SqlSession sqlSession=sqlSessionFactory.openSession(true);//第一次提交
threadLocal.set(sqlSession);
}
public static SqlSession getSqlSession(){
SqlSession sqlSession=threadLocal.get();//第一次提交
if (sqlSession == null) {
newSession();
sqlSession=threadLocal.get();//第二次提交否则空指针异常
}
return sqlSession;
}
/*3.关闭sqlSession对象,并从线程变量中删除*/
public static void closeSqlSession(){
SqlSession sqlSession=threadLocal.get();//获得
if (sqlSession != null) {
sqlSession.close();//若sqlSession不为空
threadLocal.set(null);//关闭资源清空线程变量
}
}
}
2-1资源文件目录下核心配置文件mybatis.xml/映射配置文件UserMapper.xml/日志配置文件log4j.properties
<?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>
<!--指定 MyBatis 所用日志的具体实现,未指定时将自动查找-->
<properties>
<property name="logImpl" value="LOG4J"/>
</properties>
<!--设置实体类的别名-->
<typeAliases>
<!--<typeAlias type="cn.kgc.kade2020.tyl.pojo.User" alias="user"></typeAlias>-->
<package name="cn.kgc.kade2020.tyl.pojo"/>
</typeAliases>
<!--配置环境-->
<!-- <properties resource="jdbc.properties"/>-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/smbmsdb?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--告诉mybatis去哪里找sql语句,sql映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
<!--别名中的包名对应mapper中的xml文件,实体类映射映射接口实现类-->
</configuration>
<?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="cn.kgc.kade2020.tyl.mapper.UserMapper">
<!--1.查询所有的用户信息-->
<!--id是方法名,resultType是返回类型,只有查询才有,增删改只有参数类型,修改的参数类型为对象,因为不知道修改的具体参数个数-->
<select id="getAllUser" resultType="user">
select * from user
</select>
<!--2.根据id查询用户-->
<select id="getUserById" resultType="user" parameterType="int">
select * from user where id=#{id}
</select>
<!--3.根据用户名称进行模糊查询-->
<select id="getUserByName" resultType="user" parameterType="string">
select * from user where userName like CONCAT('%',#{userName},'%')
</select>
<!--4.查询用户的个数-->
<select id="getTotalCount" resultType="int">
select count(1) from user
</select>
<!--5.添加用户-->
<insert id="addUser" parameterType="user">
insert into user(userName,userRole,password) values(#{userName},#{userRole},#{password})
</insert>
<!--6.删除用户-->
<delete id="delUser" parameterType="int">
delete from user where id=#{id}
</delete>
<!--7.根据id修改用户名-->
<update id="upUser" parameterType="user">
update user set userName=#{userName} where id=#{id}
</update>
</mapper>
### 设置###
log4j.rootLogger = debug,stdout,D
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D//logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3-0测试类
package cn.kgc.kade2020.tyl.mapper;
import cn.kgc.kade2020.tyl.pojo.User;
import cn.kgc.kade2020.tyl.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
/*
@author tangyingli
@create 2020/12/25-15:21
@version 1.0
*/public class UserMapperTest {
@Test
public void getAllUser()throws Exception {
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> userList=userMapper.getAllUser();
System.out.println(userList);
MybatisUtil.closeSqlSession();
}
@Test
public void getUserById() throws Exception{
//获得sqlSession对象s
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=userMapper.getUserById(3);
System.out.println(user);
}
@Test
public void getUserByName()throws Exception {
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> userList=userMapper.getUserByName("王");
System.out.println(userList);
MybatisUtil.closeSqlSession();
}
@Test
public void getTotalCount() throws Exception{
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
Integer res=userMapper.getTotalCount();
System.out.println(res);
MybatisUtil.closeSqlSession();
}
@Test
public void addUser() throws Exception{
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user= new User(null,"tyl",1,"1234");
Integer res=userMapper.addUser(user);
System.out.println(res);
}
@Test
public void upUser() {
User user=new User();
user.setId(3);
user.setUserName("唐远");
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
Integer res=userMapper.upUser(user);
System.out.println(res);
}
@Test
public void delUser() {
//获得sqlSession对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
Integer res=userMapper.delUser(6);
System.out.println(res);
}
}