什么是框架?
软件的半成品,解决了软件开发过程中的配适性问题,从而简化了开发步骤,提高了开发的效率。
什么是ORM框架?
ORM (Object RelationalMapping)对象关系映射,将程序中的一个对象与表中的一行数据一一对应
ORM框架提供了持久化类与表的映射关系,在运行时参照映射文件的信息,把对象持久化到数据库中
使用JDBC完成ORM操作的缺点?
存在大量的冗余代码。
手工创建 Connection、Statement等。
手工将结果集封装成实体对象。
查询效率低,没有对数据访问进行过优化(Not Cache)
MyBatis框架
“高级JDBC”
ORM框架:映射框架
框架--是一个半成品,里面使用大量的设计模式,简化书写代码,提供大了的动态sql语句以及结果映射!
入门
pom.xml导入mybatis的核心依赖
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!--mybatis的核心jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
配置 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>
<!--JDBC环境配置-->
<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>
</environments>
<!--加载mapper映射器-->
<mappers>
<!--配置mapper文件的所在位置-->
<package name="com.qf.mapper"/>
</mappers>
</configuration>
准备好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>
单元测试进行执行
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);
}
}
}
}
log4j日志
pom.xml导入依赖
<!--log4j的日志包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
resources配置文件
# 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
#跟踪具体的接口或者接口中的指定方法
log4j.logger.com.qf.mapper.UserDao=TRACE
# 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:/EE_2302/day56/code/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
查询
添加用户获取自增长id值
<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>
mybatis模糊查询
<!--
mybatis进行sql优化的时候,尽量使用#{} 占位符号
不要使用${} (字符串拼接)
推荐的写法 #{}
-->
<select id="selectUsersByUserName" parameterType="java.lang.String" resultType="com.qf.pojo.User">
select * from user where username like #{username}
</select>
通过vo实体查询指定用户
dao
/**
* 通过包装的vo实体查询指定的用户
* @param vo vo实体
* @return 返回用户
*/
User findUserByQueryVo(QueryVo vo) ;
xml
<!--通过vo实体查询指定的用户
参数形式QueryVo实体类型,里面包含另一个实体属性user属性
获取到QueryVo对象.getUser().getUsername():获取到用户名
一个实体类中的getXxx()里面xxx就是实体类的bean属性
ognl简写表达式 get()去掉,第一个字母小写
-->
<select id="findUserByQueryVo" parameterType="queryvo" resultType="user">
select * from user where username = #{user.username}
</select>
入参类型是多个参数
顺序传参
dao:
User findUserByMultConditon(String name,String addr) ;
xml:
<!--指定多个条件查询用户
按照参数的顺序进行查询,param1,param2....依次,不利于管理维护(不推荐)
-->
<select id="findUserByMultConditon" resultType="com.qf.pojo.User">
select * from user where username = #{param1} and address = #{param2}
</select>
参数绑定注解方式(推荐)
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>
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>
自定义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>
mybatis使用德鲁伊连接池
pom.xml导入依赖
<!--druid德鲁伊-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
创建配置文件
创建jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ku'm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=10
自定义一个类
创建包名datasource下
/**
* 自定义数据源工厂--提供德鲁伊的数据源DruidDataSource
*/
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
public MyDruidDataSourceFactory(){
//给数据源进行初始化
this.dataSource=new DruidDataSource();创建德鲁伊数据源
}
}
优化后的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),可以直接指定实体类的包名
所有的实体类的包名就是默认当前类名(建议小写),不区分大小写 -->
<package name="com.qf.pojo"/>
</typeAliases>
<!--配置插件-->
<plugins>
<!--插件里面属性
interceptor指定当前拦截器
-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!--环境配置-->
<environments default="mysql">
<!--可以配置多个环境-->
<environment id="mysql">
<!--mybatis事务管理器
连接数据库操作 -->
<transactionManager type="JDBC"/>
<!--启用mybatis自带的连接池-->
<!--<dataSource type="POOLED">-->
<!--启用druid连接池-->
<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>
</environments>
<!--加载mapper映射器-->
<mappers>
<!--配置接口的包名-->
<package name="com.qf.mapper"/>
</mappers>
</configuration>
Mybatis分页插件PageHelper的使用
导入分页插件依赖
<!--mybatis的分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
配置插件
<plugins>
<!--插件里面属性
interceptor指定当前拦截器
-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
业务层实现
先设置分页,再进行查询
//通过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);
}
}