1.MyBatis框架
MyBatis是一个开源的数据持久层框架,内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射。作为持久层框架,主要思想是将程序中的大量的SQL语句分离出来,配置在相应的配置文件中,这样可以在不修改代码的情况下,直接在配置文件中的修改SQL。
ORM(Object/Relational Mapping)对象关系映射。是一种数据持久化的技术。在对象模型和关系型数据库之间建立关系,并且提供了一种机制,通过JavaBean对象去操作数据库表中的数据。MyBatis通过简单的XML或者注解进行配置和原始映射,将实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。
2.MyBatis入门
1.导入mybatis的依赖
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency>
2. 需要准备配置 mybatis核心配置文件 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"> <!--xx.dtd是xml文件约束,约束标签--> <!--核心配置--> <configuration> <!--环境配置--> <environments default="mysql"> <!--可以配置多个环境--> <environment id="mysql"> <!--mybatis事务管理器 连接数据库操作 --> <transactionManager type="JDBC"/> <!--启用mybatis自带的连接池--> <dataSource type="POOLED"> <!--配置连接池这个类中的属性参数 drvier/url/username/password都是 org.apache.ibatis.datasource.pooled.PooledDataSource信息 --> <!--驱动类--> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--连接数据库的地址--> <property name="url" value="jdbc:mysql://localhost:3306/myee2302_db_2"/> <!--用户名--> <property name="username" value="root"/> <!--登录密码--> <property name="password" value="123456"/> </dataSource> </environment> <!--配置其他环境--> <!--<environment id="oracle"> <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>
3.准备好mybatis的持久层接口以及它的映射文件
public interface AccountDao { /** * 查询所有账户 * @return 返回账户列表 */ List<Account> findAllAccounts() ; } <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--映射器的配置 namesapce:名称空间指定接口的完全限定名称 --> <mapper namespace="com.qf.mapper.AccountDao"> <!--大量的sql标签 id必须和接口文件中的方法名必须一致 当前接口中的方法有返回值,返回值如果是实体类型或者是List集合 输出映射:resultType必须要指定为当前实体类型的完全限定名称 --> <select id="findAllAccounts" resultType="com.qf.pojo.Account"> select * from account </select> </mapper>
4.单元测试进行执行
package com.qf.mybatistest; import com.qf.mapper.AccountDao; import com.qf.pojo.Account; 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 org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; /** * @author 高圆圆 * @date 2023/5/5 14:48 * 单元测试类 */ public class MybatisTest { @Test public void testFindAll() throws IOException { //1)读取resource下面的mybatis-config.xml文件 //org.apache.ibatis.io.Resources --InputStream getResourceAsStream(配置文件名称) InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //2)创建一个对象SqlSessionFactoryBuilder SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder() ; //3)创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载流对象 获取到工厂对象 //4)创建 SqlSession---就是执行对象--底层就是PreparedStatement SqlSession sqlSession = sqlSessionFactory.openSession();//自动提交 //5)获取AccountDao接口对象---通过mybatis的动态代理获取接口对象 AccountDao accountDao = sqlSession.getMapper(AccountDao.class);//接口类型字节码文件 //6)调用方法 List<Account> allAccounts = accountDao.findAllAccounts(); if(allAccounts!=null || allAccounts.size()>0){ for(Account account :allAccounts){ System.out.println(account); } } } }
3.mybatis的涉及到的设计模式
4.mybatis关于模糊查询的语法
1、模糊查询的第一种方式
首先回顾一下sql中的模糊查询,如下select * from student where name like "%力"
Mybatis中,第一种方式就是在java代码的参数中写好like后面的内容,然后以参数的的形式传入mapper文件 进行拼接。
示例:
dao接口的模糊查询方法
//like第一种方式
List<Student> selectLikeOne(@Param("name") String name);
mapper文件
<!--like第一种方式--> <select id="selectLikeOne" resultType="com.bjpowernode.domain.Student"> select * from student where name like #{name} </select>
Test测试方法
@Test public void testLikeOne(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); String name="%李%"; List<Student> students = dao.selectLikeOne(name); sqlSession.close(); students.forEach( stu-> System.out.println(stu)); }
2、模糊查询的第二种方式
Mybatis中第二种模糊查询的方法不是在java代码中,比如上面的测试方法里面给出模糊查询的完整内容。而是将匹配符放在mapper文件中,然后只把需要匹配的关键字暴露出来自定义即可,显然第二种方式更具有体验感。示例:
dao接口方法
//like第二种方式
List<Student> selectLikeTwo(@Param("name") String name);
mapper文件,注意:sql语句like的写法
<!--like第二种方式-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student"> select * from student where name like "%" #{name} "%" </select>
测试方法, 注意:这里的name的内容不需要在加入%符号,只需要匹配的关键字即可
@Test public void testLikeTwo(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); String name="李"; List<Student> students = dao.selectLikeTwo(name); sqlSession.close(); students.forEach( stu-> System.out.println(stu)); }
5.数据插入获得自增主键
mysql:支持自增主键
<insert id="addUser" parameterType="com.qf.pojo.User" > <!--在插入的时候,获取id自增长主键的值,配置一些函数 selectKey 属性 keyColumn:表的主键字段名称 keyProperty:实体类的属性名称 resultType:返回值自增长主键的值类型:当前实体类的完全限定名称或者别名 order:AFTER:在执行插入语句之后执行selectkey的语句获取最后一次id的值 --> <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER"> <!--通过这个函数获取最后一次自增长主键的id值--> SELECT LAST_INSERT_ID() ; </selectKey> insert into user(username,gender,age,address) values(#{username},#{gender},#{age},#{address}) </insert>
oracle:不支持自增主键,靠序列来完成
在要执行的sql前用 selectKey 标签来实现
相关的三个属性分别是 keyProperty、resultType 和 order;
有两种写法分别是 order 的属性值为 before 和 after;通常使用 before
6.映射文件的参数处理
6.1单个参数
单个参数可以在 #{}中随意写;
6.2 多个参数
6.2.1按照参数的顺序进行查询
dao:
xml:User findUserByMultConditon(String name,String addr) ;
<!--指定多个条件查询用户 按照参数的顺序进行查询,param1,param2....依次,不利于管理维护(不推荐) --> <select id="findUserByMultConditon" resultType="com.qf.pojo.User"> select * from user where username = #{param1} and address = #{param2} </select>
6.2.2启用mybatis的@Param注解
dao:
//启用mybatis的@Param注解--指定绑定参数名称,这个参数名称就是等会需要赋值的参数(#{参数名称}) User findUserByMultConditon(@Param("username") String name, @Param("address") String addr) ;
xml:
<!-- 指定多个条件查询用户的方式2:使用mybatis参数绑定注解方式(推荐) #{}里面的内容需要和@Param里面的参数名称一致 --> <select id="findUserByMultConditon" resultType="com.qf.pojo.User"> select * from user where username = #{username} and address = #{address} </select>
6.2.3 使用Map集合接收所有参数
dao:
//使用Map集合接收所有参数 --复杂类型 User findUserByMultConditon(Map<String,String> map) ;
xml:
<!-- 指定多个条件查询的方式3:使用Map集合 #{}里面的内容需要和map集合的key一致 --> <select id="findUserByMultConditon" resultType="com.qf.pojo.User"> select * from user where username = #{name} and address = #{addr} </select>
6.2.4 自定义vo实体封装
vo实体类
根据前端需要的具体参数,视情况而定vo类的属性@Data @NoArgsConstructor @AllArgsConstructor public class VoUser { private String name ; private String address ; }
dao:
//通过自定义的实体类,将查询的参数封装到这个类中 User findUserByMultConditon(VoUser voUser) ;
xml:
<!-- 指定多个条件查询的方式4:使用自定义vo实体,将参数放在实体中 --> <select id="findUserByMultConditon" resultType="com.qf.pojo.User" parameterType="com.qf.pojo.VoUser"> select * from user where username = #{name} and address = #{address} </select>
7. log4j日志
pom.xml导入依赖
<!--log4j的日志包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
resources配置文件 log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/log4j.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
8.使用德鲁伊连接池
1. pom.xml导入依赖
<!--druid德鲁伊-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
2.创建配置文件----jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myee_2208?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=10
3.自定义一个类------创建包名datasource下的 MyDruidDataSourceFactory.java
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
public MyDruidDataSourceFactory(){
//给数据源进行初始化
this.dataSource = new DruidDataSource() ;//创建德鲁伊数据源
}
}
9.优化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">
<!--xx.dtd是xml文件约束,约束标签-->
<!--核心配置-->
<configuration>
<!--属性配置
加载外部配置文件
-->
<properties resource="jdbc.properties"></properties>
<!--实体类的别名配置-->
<typeAliases>
<!--type指定的当前实体类的完全限定名称
alias:实体的类别名(自己指定,见名知意)
这种方式麻烦(实体类很多,配置很多个typeAlias),可以直接指定实体类的包名
所有的实体类的包名就是默认当前类名(建议小写),不区分大小写
-->
<!--<typeAlias alias="user" type="com.qf.pojo.User"></typeAlias>
<typeAlias alias="vouser" type="com.qf.pojo.VoUser"></typeAlias>
<typeAlias alias="queryvo" type="com.qf.pojo.QueryVo"></typeAlias>-->
<package name="com.qf.pojo"/>
</typeAliases>
<!--环境配置-->
<environments default="mysql">
<!--可以配置多个环境-->
<environment id="mysql">
<!--mybatis事务管理器
连接数据库操作
-->
<transactionManager type="JDBC"/>
<!--启用mybatis自带的连接池-->
<!--<dataSource type="POOLED">-->
<dataSource type="com.qf.datasource.MyDruidDataSourceFactory">
<!--配置连接池这个类中的属性参数
drvier/url/username/password都是
org.apache.ibatis.datasource.pooled.PooledDataSource信息
-->
<!--驱动类-->
<!--
${获取外部资源文件的key对应的内容}
-->
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<!--连接数据库的地址-->
<property name="url" value="${jdbc.url}"/>
<!--用户名-->
<property name="username" value="${jdbc.username}"/>
<!--登录密码-->
<property name="password" value="${jdbc.password}"/>
<!--最大激活数-->
<property name="maxActive" value="${jdbc.maxActive}"/>
</dataSource>
</environment>
<!--配置其他环境-->
<!--<environment id="oracle">
<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>
<!--加载mapper映射器-->
<mappers>
<!--配置多个mapper-->
<!-- <mapper resource="com/qf/mapper/EmployeeDao.xml"></mapper>
<mapper resource="com/qf/mapper/UserDao.xml"></mapper>-->
<package name="com.qf.mapper"/>
</mappers>
</configuration>
10.分页
1.导入分页插件依赖(注:不使用分页的情况下,不配置分页依赖)
<!--mybatis的分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2.配置插件
<plugins>
<!--插件里面属性
interceptor指定当前拦截器
-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3.业务层实现---先设置分页,再进行查询
//通过mybatis的分页插件完成分页条件
//PageHelper父类有一个API---
//参数:pageNum:当前页码
// pageSizeL
//public static <E> Page<E> startPage(int pageNum, int pageSize)
//当前页码1,每页显示3条
PageHelper.startPage(1,3) ;
//6)调用方法
List<User> users = userDao.findAll(); //获取分页列表数据
//创建PageInfo对象
PageInfo pageInfo = new PageInfo(users) ;
System.out.println(pageInfo); //展示分页的数据
if(users!=null || users.size()>0){
for(User user :users){
System.out.println(user);
}
}