一、什么是框架
框架是一种经过校验、具有一定功能的半成品软件品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度。
二、什么是ORM
三、什么是mybatis框架?
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀==ORM框架==。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索封装。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录. 半自动化框架。必须写sql语句。
mybatis可以向PreparedStatement中输入参数自动进行输入映射,将查询结果集灵活的映射成Java对象(输出映射),输入映射和输出映射这是mybatis的核心
用一句话来说, mybatis就是封装与数据库交互的半成品。
1、如何使用mybatis
准备条件就是需要先建一个数据
create database mybatis;
use mybatis;
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, NAME
VARCHAR(20), age INT);
INSERT INTO users(NAME, age) VALUES('Tom', 12);
INSERT INTO users(NAME, age) VALUES('Jack', 11);
(1)创建一个maven的java工程
(2)引入mybatis的jar包和 mysql的驱动jar包
(3)创建相应的实体类
(4)配置mybatis的配置文件---mybatis会读取该文件的内容完成连接数据库的功能
(5)编写相应的映射(mapper)文件 -----sql语句 实体类与表的映射
(6)把映射文件引入到mybatis配置文件中
(7)测试是否成功
(8)CRUD操作 (增删改查)测试
2、实际开发中使用Dao
(1)定义一个相关的Dao接口
(2)映射文件(mapper)
注意: namespace必须和接口所在的路径对应。id必须和方法名一致
(3)测试
(4)注意红框位置(mybatis03)
3、传递多个参数
图中非注释区域对应的是自定义参数名 @Param("参数名")
4、特殊字符
(1)常见的特殊字符
(2)解决方式有两种
①是转义字符,如上图所示
②是使用<![CDATA[ 特殊字符或SQL语句 ]]>
5、mybatis的优化
(1)引入db属性文件。
①定义一个数据库属性文件 . properties
②在mybatis配置文件中引入属性文件并使用相应的key
(2)引入日志文件 ——更好的显示sql语句
①引入日志jar包
②引入日志的配置文件 log4j.properties
输出到日志文件
### 输出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### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
(3)解决列名和属性名不一致
①为查询的列起别名;让别名和属性名一致
<select id="selectById" resultType="com.ykq.entity.Order">select order_id id,order_no no,order_price price from orders where order_id=#{id}
</select>
②使用resultMap标签 来完成属性和列的映射关系
<!--id:唯一标识type:类型;表与哪个实体类的映射<id 主键的映射关系 column="列名" property="属性名"/><result 普通字段/>autoMapping = true 表示自动映射 默认一般为true--><resultMap id="l" type="com.ljm.entity.Book_info"><!--id必须写--><id property="id" column="book_id"/><result property="name" column="book_name"/><result property="author" column="book_author"/><result property="price" column="book_price"/><result property="pub" column="book_pub"/></resultMap><select id="selectById" resultMap="l">select * from book_info where book_id=#{id}</select>
追加:事务
什么是事务:事务是由一系列动作组成,这些动作要么都完成,要么都不完成。
jdbc默认事务是自动提交。现在mybatis事务需要手动提交。
//转账问题
Connection connection=null;
try {Class.forName("com.mysql.cj.jdbc.Driver");connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai","root","root");connection.setAutoCommit(false);PreparedStatement ps=connection.prepareStatement("update users set age=age-10 where name='张天龙'");ps.executeUpdate();ps=connection.prepareStatement("update users set age=age+10 where name='汪伟宁'");ps.executeUpdate();//connection.commit();//提交
}catch (Exception e){try {connection.rollback();//回滚} catch (SQLException throwables) {throwables.printStackTrace();}e.printStackTrace();
}finally {}
6、链表查询
(1)多对一 ①链表查询 ②嵌套查询
<!--链表查询-->
<resultMap id="ljm01" type="com.ljm.entity.Emp"><id property="eno" column="empno"/><result property="name" column="name"/><result property="job" column="job"/><result property="sal" column="sal"/><!--association 表示多对一property 表示对象属性名 javaType 表示该对象所属的类型--><association property="dept" javaType="com.ljm.entity.Dept" autoMapping="true"><!--Dept和Dept表的对应关系--><id property="dno" column="deptno"/></association></resultMap><select id="selectById" resultMap="ljm01">select * from emp e join dept d on e.depton=d.deptno where e.empno=#{eno}</select>
<!--嵌套查询 两次查询--><resultMap id="ljm01" type="com.ljm.entity.Dept" autoMapping="true"><id property="dno" column="deptno"/></resultMap><select id="selectById" resultMap="ljm01">select * from dept where deptno=#{depton}</select><resultMap id="ljm02" type="com.ljm.entity.Emp"><id property="eno" column="empno"/><result property="name" column="name"/><result property="job" column="job"/><result property="sal" column="sal"/><!--column 把查询的哪一列作为另一个查询的条件值select 表示引用另一个查询--><association property="dept" javaType="com.ljm.entity.Dept" autoMapping="true">column="depton" select="com.ljm.dao.DeptDao.selectById" <!--Dept和Dept表的对应关系--></association></resultMap><select id="selectById02" resultMap="ljm02">select * from emp where empno=#{eno}</select>
(2)一对多
<--链表查询-->
<resultMap id="ljm03" type="com.ljm.entity.Clazz" autoMapping="true"><id property="cid" column="cid"/><!--collection: 集合的意思 多的意思property:集合对象名ofType 集合的泛型--><!--若属性名和数据库的列名一直,则不需要在写,直接autoMapping即可,但是id必须写--><collection property="students" ofType="com.ljm.entity.Student" autoMapping="true"><id property="sid" column="sid"/></collection></resultMap><select id="findById" resultMap="ljm03">select * from class c join student s on c.cid=s.classid where cid=#{cid}</select>
7、动态sql语句
元素 | 作用 | 描述 |
---|---|---|
if | 条件判断 | 单条件判断 |
choose(when、otherwise) | 条件选择,相当于java when | 多条件分支判断 |
where、set | 辅助 | 处理sql拼接语句 |
foreach | 循环 | 循环 |
<resultMap id="book" type="com.ljm.entity.Book"><id property="id" column="book_id"/><result property="name" column="book_name"/><result property="author" column="book_author"/><result property="price" column="book_price"/><result property="pub" column="book_pub"/></resultMap>
(1)if和where一起用
<!--如果传入书名 按书名进行查询 如果没有传入书名 则查询所有where 可以添加where关键字,并把第一个and或者or去除--><!--if+where--><select id="findByCondition" resultMap="book">select * from book_info<where><if test="bookname!=null and bookname!=''">and book_name=#{bookname}</if><if test="author!=null and author!=''">and book_author=#{author}</if></where></select><--测试-->
@Testpublic void test(){BookDao bookDao = session.getMapper(BookDao.class);HashMap<String, Object> map = new HashMap<String, Object>();map.put("bookname","西游记");map.put("author","吴承恩");List<Book> list = bookDao.findByCondition(map);//System.out.println(list);}
(2)[choose when otherwise] 和where
<!--choose+wherewhen 条件满足时不会执行下面的when和otherwise 都不满足执行otherwise满足第一个条件后面就不再进行了,不满足第一个条件就进行第二个,否则就进行第三个--><select id="findByCondition02" resultMap="book">select * from book_info<where><choose><when test="bookname!=null and bookname!=''">and book_name=#{bookname}</when><when test="author!=null and author!=''">and book_author=#{author}</when><otherwise>and book_price>35</otherwise></choose></where></select><--测试-->
@Testpublic void test1(){BookDao bookDao = session.getMapper(BookDao.class);HashMap<String, Object> map = new HashMap<String, Object>();map.put("bookname","西游记");map.put("author","吴承恩");List<Book> list = bookDao.findByCondition(map);//System.out.println(list);}
(3)set标签 修改部分字段
<!--set 修改部分列的值可以添加set关键字 并去除最后的逗号--><update id="update">update book_info<set><if test="name!=null and name!=''">book_name=#{name},</if><if test="author!=null and author!=''">book_author=#{author},</if><if test="pub!=null and pub!=''">book_pub=#{pub},</if><if test="price!=null">book_price=#{price},</if></set>where book_id=#{id}</update><--测试-->
@Testpublic void testUpdate(){BookDao bookDao = session.getMapper(BookDao.class);Book book = new Book();book.setAuthor("罗贯中");book.setName("三国");book.setId(1010);bookDao.update(book);session.commit();}
(4)foreach 批量删除
<!--foreach collection 变量的集合 item 每次遍历时赋值的元素变量名open 以什么开始 close 以什么结束 separator 分隔符--><delete id="batchDelete">delete from book_info where book_id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></delete><--测试-->
@Testpublic void batchDelete(){BookDao bookDao = session.getMapper(BookDao.class);int[] ids = {1001,1002,1003};bookDao.batchDelete(ids);session.commit();}
8、模糊查询
<!--模糊查询--><select id="findAll01" resultMap="ljm01">select<include refid="sql01"/>from emp e join dept d on e.depton=d.deptno<where><if test="name!=null and name!=''">name like concat('%',#{name},'%')</if></where></select><--测试-->
//模糊查询@Testpublic void testFindAll(){EmpDao empDao = session.getMapper(EmpDao.class);List<Emp> list = empDao.findAll01("老");System.out.println(list);//session.commit();}
9、分页插件
(1) 引入相关的pageHelper依赖 pom
<!--分页插件的依赖--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.11</version></dependency>
(2) 加入拦截 mybatis
<!--分页拦截--><plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor="com.github.pagehelper.PageInterceptor"><!-- 使用下面的方式配置参数,后面会有所有的参数介绍 --><property name="param1" value="value1"/></plugin></plugins>
(3)测试
//测试分页@Testpublic void testFindAll1(){EmpDao empDao = session.getMapper(EmpDao.class);//使用分页功能PageHelper.startPage(2,8);List<Emp> list = empDao.findAll01("老");//可以把查询的结果封装到PageInfo类中,包含总条数//PageInfo<Emp> pageInfo = new PageInfo<Emp>(list);//System.out.println("总数:"+pageInfo.getTotal());System.out.println(list);}