1 Mybatis是什么(理解)
(1)mybatis : 一个基于Java的持久层框架
(2)持久层 : 操作数据库那层代码
(项目分层:界面层(jsp/controller) 业务层(service层) 持久层(数据层 dao层))
持久层框架 : jdbc , springjdbc jpa springdatajpa , mybatis
(3) 框架:
a) 每个框架为了解决==某一个领域==问题产生
b)框架还是一个半成品, 已经完成一部分功能 ,只需要在上面进行开发 --提高开发效率
c) 可以让我们很多人写的代码 都按照一定规则去写--可读性 维护性
(4)持久化概念:
把内存里面数据 保存到数据库中 --过程就叫持久化
(5)mybatis 它是一个持久层框架,同时又是ORM的框架
ORM: 对象关系映射 --jpa/springdatajpa
2 Mybatis的特点(理解)
(1)MyBatis 是一个支持普通 SQL查询,存储过程(数据库mysql/oracle)和高级映射的优秀持久层框架。
(2)MyBatis *消除了几乎所有的JDBC代码和手工设置参数以及结果集的检索*。
jdbc:
a) 贾琏欲执事 -- 不需要做
b) 手工设置参数(传参) -- 不需要做
insert into xxx (name,age) values(?,?)
c) 结果集 ResultSet(返回值) -- 不需要做
(3)MyBatis 使用简单的 *XML*或 注解 用于配置和原始映射,将接口和 Java 的*POJOs*(Plain Old Java Objects,普通的 Java对象 Employee/User/Entity/Domain)映射成数据库中的记录。 SQL映射方式
xxxMapper.xml 文件(crud sql语句)
面试题 : Jpa缓存
jpa 一级缓存 和二级缓存 是什么?
jpa 一级缓存: 属于entityManager级别缓存,jpa自带的,不用做任何配置, 命中条件
同一个entityManageFactory ,同一个EntityManager 同一个OID
二级缓存: 属于entityManagerFactory级别缓存,不是自带 ,需要做相应配置才行
命中条件
同一个entityManageFactory ,不同一个EntityManager 同一个OID
面试题 : jdbc和mybatis优缺点?
jdbc和mybatis优缺点?
(1)jdbc操作步骤比较繁琐,比较执行贾琏欲执事 而mybatis不用 消除这个代码
(2)jdbc需要自己手动设置 参数 以及处理返回结果集 --而mybatis 不需要
(3)mybatis 可以采用 xml 和 注解 来写sql ...jdbc 把sql 写到代码里面, 可以提高维护性
(4)jdbc 它是操作数据库最底层的代码,mybatis也是从jdbc上面封装出来框架 mybatis支持缓存
3 使用Mybatis(掌握)
(1) 创建项目 导入jar包
a)创建一个普通项目 , 创建一个文件夹lib (jar包)
b)数据库创建一个表 Product
c)创建结构
cn.itsource.mybatis.domain
cn.itsource.mybatis.dao
cn.itsource.mybatis.service
(2) 做相应的配置
Mybatis-config.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> <!-- 开发环境--> <environments default="development"> <!-- 一个环境 id:为这个环境取唯一一个id名称 --> <environment id="development"> <!-- 事务管理 type:JDBC(支持事务)/MANAGED(什么都不做) mysql: innodb MyISAM --> <transactionManager type="JDBC" /> <!-- 数据源, 连接池 type(POOLED):MyBatis自带的连接池 --> <dataSource type="POOLED"> <!-- 连接数据库的参数 四大金刚 --> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql:///mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 这个mappers代表的是相应的ORM映射文件 --> <mappers> <mapper resource="cn/itsource/mybatis/domain/ProductMapper.xml" /> </mappers> </configuration>
ProductMapper.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:命名空间 以后:通过namespace+id 调用对应的语句 --> <mapper namespace="cn.itsource.mybatis.domain.ProductMapper"> <!-- select:表示查询标签 id: 代表给标签取个名称 必须唯一 resultType:返回值类型 --> <select id="findAll" resultType="cn.itsource.mybatis.domain.Product"> select * from product </select> </mapper>
(3) 写测试类测试一下
@Override public List<Product> findAll() throws IOException { //读取配置 Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); //SqlSessionFactory -->EntityManagerFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); //SqlSession -->EntityManager SqlSession sqlSession = sqlSessionFactory.openSession(); //调用findAll +namespace+id List<Product> products = sqlSession. selectList("cn.itsource.mybatis.domain.ProductMapper.findAll"); return products; }
4 完成crud(掌握)
<?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+id 调用对应的语句 --> <mapper namespace="cn.itsource.mybatis.domain.ProductMapper"> <!-- select:表示查询标签 id: 代表给标签取个名称 必须唯一 resultType:返回值类型 --> <select id="findAll" resultType="cn.itsource.mybatis.domain.Product"> select * from product </select> <!--新增 parameterType 参数类型--> <insert id="save" parameterType="cn.itsource.mybatis.domain.Product"> insert into product(productName,salePrice,costPrice,cutoff) values(#{productName},#{salePrice},#{costPrice},#{cutoff}) </insert> <!--修改--> <update id="update" parameterType="cn.itsource.mybatis.domain.Product"> update product set productName=#{productName},salePrice=#{salePrice} where id=#{id} </update> <!--删除 long Mybatis内置别名 long java.util.Long remove(13)--> <delete id="remove" parameterType="long"> delete from product where id=#{id} </delete> <!--查询一条数据--> <select id="findOne" parameterType="long" resultType="cn.itsource.mybatis.domain.Product"> select * from product where id=#{id} </select> </mapper>
5 工具类(掌握)
枚举方式
public enum MybatisUtil { INSTANCE; private static SqlSessionFactory sqlSessionFactory; //静态代码块 static{ Reader reader = null; try { reader = Resources.getResourceAsReader("mybatis-config.xml"); //SqlSessionFactory -->EntityManagerFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } //抽取一个 --sqlSession public SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
6 mybatis使用细节(掌握)
6.1 细节1 -- 主键问题(掌握)
有时候 保存一条数据之后,需要拿到这条数据的主键,拿到之后可以做后续事情
场景:
角色的保存
useGeneratedKeys="true" keyColumn="id" keyProperty="id"
<insert id="save" parameterType="cn.itsource.mybatis.domain.Product" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> insert into product(productName,salePrice,costPrice,cutoff) values(#{productName},#{salePrice},#{costPrice},#{cutoff}) </insert>
6.2 细节2 --日志问题(掌握)
(1)为什么要使用日志
有时候,需要打印的sql的信息 比如sql的传参数 返回值 -- 必须使用日志
好处: 使用日志框架可以帮助我们进行分析与排错
(2)常见排错方式:
断点
System.out.println
输出日志
(3)日志框架:
a)自己写:
通过反射技术 ,可以拿到参数 可以方法 拿到返回值
b)log4j -- 使用比较多
c)日志框架标准
以前没有日志框架的, 每个人处理日志 都不一样 ..
日志标准 -- slf4j(抽象标准) -->很多实现 logging,logback,log4j
(4)使用日志框架 log4j(掌握)
a)导入jar包
b)写一个配置文件
log4j.rootLogger=ERROR, stdout 日志等级(了解): OFF level > FATAL(致命) > ERROR(错误) > WARN (警告)> # INFO (提示)> DEBUG (调试)> trace > ALL level(所有配置)\ #输出效果 如果你设置日志级别是trace,则大于等于这个级别的日志都会输出 # 关闭日志输出 #log4j.rootLogger=NONE 不想打印日志 就配置NONE # WARN为一般警告,比如session丢失、 # INFO为一般要显示的信息,比如登录登出、 # DEBUG为程序的调试信息 # TRACE 堆栈信息 # 扫描包 配置自己包 #注意点 包名/配置等级 配置DEBUG/ALL log4j.logger.cn.itsource=DEBUG/TRACE #ConsoleAppender:输出控制台 log4j.appender.stdout=org.apache.log4j.ConsoleAppender #layout: 格式样式 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout #采用下面的样式输出 [20191224]类名 log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
6.3 细节3--掌握
#与$区别 --面试题
3点区别
(1) $ 取得对象里面的某个属性 比如 ${id} Long getId ${id} # 都可以 (2)重点 # select * from product where productName = ? 预编译的对象 $ select * from product where productName = 罗技G500 拼接字符串方式 # 推荐使用 $ sql注入问题 (3)后面使用$的 orderby+limit 后面就order by age/id不需要添加引号
7 动态SQL(掌握)
比如: 以前做高级查询的时候 select * from xx where ... and ...
高级查询核心内容:就是where后面拼接
<sql id="whereSql"> <where> <if test="productName != null"> and productName = #{productName} </if> <if test="id != null"> and id = #{id} </if> </where> </sql> <select id="queryByCondition" parameterType="cn.itsource.mybatis.query.ProductQuery" resultType="cn.itsource.mybatis.domain.Product"> select * from product <include refid="whereSql"></include> </select>
8 批量操作(掌握)
批量删除--(列表页面 checkbox 多选框)