网站推广办法,网创电商是什么,网站建设博客,土木工程毕设代做网站MyBatis简介
MyBatis 是一款优秀的持久层框架#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO#xff08;Plain Old Ja…MyBatis简介
MyBatis 是一款优秀的持久层框架它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJOPlain Old Java Objects普通老式 Java 对象为数据库中的记录。
持久层框架对比
JDBC SQL 夹杂在Java代码中耦合度高导致硬编码内伤维护不易且实际开发需求中 SQL 有变化频繁修改的情况多见代码冗长开发效率低 Hibernate 和 JPA 操作简便开发效率高程序中的长难复杂 SQL 需要绕过框架内部自动生成的 SQL不容易做特殊优化基于全映射的全自动框架大量字段的 POJO 进行部分映射时比较困难。反射操作太多导致数据库性能下降 MyBatis 轻量级性能出色SQL 和 Java 编码分开功能边界清晰。Java代码专注业务、SQL语句专注数据开发效率稍逊于 Hibernate但是完全能够接收
开发效率HibernateMybatisJDBC
运行效率JDBCMybatisHibernate
注
MyBatis 框架下SQL语句编写位置发生改变从原来的Java类改成XML或者注解定义
推荐在XML文件中编写SQL语句让用户能更专注于 SQL 代码不用关注其他的JDBC代码。
Mybatis 中的 Mapper 接口相当于以前的 Dao。但是区别在于Mapper 仅仅只是建接口即可我们不需要提供实现类具体的SQL写到对应的Mapper文件
MyBatis案例
Employee类
package com.ergou.pojo;public class Employee {private Integer empId;private String empName;private Double empSalary;//getter | setterpublic Integer getEmpId() {return empId;}public void setEmpId(Integer empId) {this.empId empId;}public String getEmpName() {return empName;}public void setEmpName(String empName) {this.empName empName;}public Double getEmpSalary() {return empSalary;}public void setEmpSalary(Double empSalary) {this.empSalary empSalary;}
}Mapper接口
package com.ergou.mapper;import com.ergou.pojo.Employee;public interface EmployeeMapper {
//根据id查询员工信息
Employee queryById(Integer id);
//根据id删除员工
int deleteById(Integer id);
}EmployeeMapper.xml:sql语句写在其中
?xml version1.0 encodingUTF-8?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- namespace等于mapper接口类的全限定名,这样实现对应--
!--xml方式写sql语句
mybatis固定在特定的标签内写sql语句
mapper的xml文件要有约束--
mapper namespacecom.ergou.mapper.EmployeeMapper!--查询使用 select标签id 方法名resultType 返回值类型标签内编写SQL语句mapper接口下不能方法重载否则全限定符对应不到唯一的方法
--
select idqueryById resultTypecom.ergou.pojo.Employee
!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解--
SELECT emp_id empId,emp_name empName, emp_salary empSalaryFROM t_empWHERE emp_id #{empId}/selectdelete iddeleteByIdDELETE FROM t_emp WHERE emp_id #{id}/delete
/mappermybatis-config.xml配置mybatis框架
?xml version1.0 encodingUTF-8?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configuration!-- environments表示配置Mybatis的开发环境可以配置多个环境在众多具体环境中使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。--
environments defaultdevelopment
!-- environment表示配置Mybatis的一个具体的环境--
environment iddevelopment
!-- Mybatis的内置的事务管理器--
transactionManager typeJDBC/
!--配置数据源--
dataSource typePOOLED
!--建立数据库连接的具体信息--
property namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://localhost:3306/mybatis-example/property nameusername valueliergou/property namepassword valueliergou070509//dataSource/environment/environmentsmappers
!-- Mapper注册指定Mybatis映射文件的具体位置--!-- mapper标签配置一个具体的Mapper映射文件--!-- resource属性指定Mapper映射文件的实际存储位置这里需要使用一个以类路径根目录为基准的相对路径--!--对Maven工程的目录结构来说resources目录下的内容会直接放入类路径所以这里我们可以以resources目录为基准--
mapper resourcemappers/EmployeeMapper.xml//mappers/configuration测试
Test
public void test_01() throws IOException {
//1.读取外部配置文件
InputStream ips Resources.getResourceAsStream(mybatis-config.xml);
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(ips);
//3.根据sqlSessionFactory创建sqlSession每次业务创建一个用完就释放
SqlSession sqlSession sqlSessionFactory.openSession();
//4.获取接口的代理对象
EmployeeMapper mapper sqlSession.getMapper(EmployeeMapper.class);
//调用方法
Employee employee mapper.queryById(1);System.out.println(employee);
//5.提交事务非DQL和释放资源
sqlSession.commit();sqlSession.close();
}ibatis方式和原理
mybatis进行数据库的crud是对ibatis的封装和优化
ibatis方式进行数据库操作 不要求写对应的mapper接口直接创建mapper.xml文件在内部编写xml文件namespace属性没有要求随便写一个字符串内部通过crud标签声明对应的sql语句即可 StudentMapper.xml文件
?xml version1.0 encodingUTF-8?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtd
!--namespacemapper对应接口的全限定符--
!--ibatis方式进行数据库操作1.不要求写对应的mapper接口2.直接创建mapper.xml文件在内部编写xml文件3.namespace属性没有要求随便写一个字符串--
mapper namespaceStudentMapperselect idquery resultTypecom.ergou.pojo.StudentSELECT * FROM student WHERE sid #{id}/select
/mapper在对应的config.xml文件中的mapper标签中配置StudentMapper.xml
mappers
!-- Mapper注册指定Mybatis映射文件的具体位置--!-- mapper标签配置一个具体的Mapper映射文件--!-- resource属性指定Mapper映射文件的实际存储位置这里需要使用一个以类路径根目录为基准的相对路径--!--对Maven工程的目录结构来说resources目录下的内容会直接放入类路径所以这里我们可以以resources目录为基准--
mapper resourcemappers/EmployeeMapper.xml/mapper resourcemappers/StudentMapper.xml/
/mappers测试
Test
public void test_02() throws IOException {
//1.读取外部配置文件
InputStream ips Resources.getResourceAsStream(mybatis-config.xml);
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(ips);
//3.根据sqlSessionFactory创建sqlSession每次业务创建一个用完就释放
SqlSession sqlSession sqlSessionFactory.openSession();
//4.直接sqlSession提供的crud方法进行数据库查询即可
//方法名为select / insert / delete / update//selectOne和selectList方法参数1为sql标签对应的id值参数二为执行sql语句传入的参数
Student student sqlSession.selectOne(StudentMapper.query, 1);System.out.println(student);
//5.提交事务非DQL和释放资源
sqlSession.commit();sqlSession.close();
}缺点其中的selectOne和selectList方法只能传一个参数
而在mybatis中可以自定义相应的sql语句和相应的方法
mybatis基本使用
向sql语句传参
#{} #{}是作为占位符给指定目标赋值当值传入占位符时就会给指定目标传入此值 ${} ${}是作为拼接块将传入的值以字符串的形式拼接在sql语句后 建议使用#{}防止外界sql注入而改变sql语句原本的意思
${}在动态的列名、表名、关键字等处使用
//注解方式传入参数
Select(select * from user where ${column} #{value})
User findByColumn(Param(column) String column,Param(value) String value);数据输入
简单类型
这里的简单类型指的是单值的类型的变量比如基本数据类型和字符串类型一个变量中只有一个数据值。
!--若传入的是单个简单类型值#{}中间的名字随便写因为传入的值为单个值的数据不存在需要辨别--
delete iddeleteByIdDELETE FROM t_emp WHERE emp_id #{id}
/delete单个实体对象传入
若传入的是单个实体对象#{}中间的名字要与要传入的值的的属性名一致以方便对应赋值
!--若传入的是单个实体对象#{}中间的名字要与要传入的值的的属性名一致以方便对应赋值--
insert idinsertEmployeeINSERT INTO t_emp(emp_name,emp_salary)VALUES(#{empName},#{empSalary})
/insert多个简单类型传入
方式①使用注解Param指定多个简单参数的key在#{}中使用的名称
//根据员工姓名和工资查询员工信息
ListEmployee queryByNameAndSalary(Param(a) String name,Param(b) Double salary);!--若传入的是多个简单类型的值--
select idqueryByNameAndSalary resultTypecom.ergou.pojo.EmployeeSELECT emp_id empId,emp_name empName,emp_salary empSalaryFROM t_empWHERE emp_name #{a} AND emp_salary #{b}
/select方案②mybatis默认机制使用默认的名字arg0arg1……形参列表中每个参数的key名字默认为arg0arg1arg2以此类推以0开头或使用param1param2……默认以1开头
Map类型参数传入
若传入的是Map类型的数据#{}中直接写Map集合中要传入的value值对应的key值即可
!--若传入的是Map类型的数据#{}中直接写Map集合中要传入的value值对应的key值即可--
insert idinsertEmployeeMapINSERT INTO t_emp(emp_name,emp_salary)VALUES(#{name},#{salary})
/insert数据输出
数据输出总体上有两种形式 增删改操作返回的受影响行数直接使用 int 或 long 类型接收即可查询操作的查询结果 单个简单类型
若是DML语句返回受影响行数则不需要手动指定返回值类型
!--若是DML语句返回受影响行数则不需要手动指定返回值类型--
delete iddeleteByIdDELETE FROM t_emp WHERE emp_id #{id}
/delete若是查询语句需要指定输出类型使用resultType属性值在相应的select标签中指定返回值类型
resultType属性值的语法
①类的全限定符
②别名的简称
别名映射的类型_bytebyte_char (since 3.5.10)char_character (since 3.5.10)char_longlong_shortshort_intint_integerint_doubledouble_floatfloat_booleanbooleanstringStringbyteBytechar (since 3.5.10)Charactercharacter (since 3.5.10)CharacterlongLongshortShortintIntegerintegerIntegerdoubleDoublefloatFloatbooleanBooleandateDatedecimalBigDecimalbigdecimalBigDecimalbigintegerBigIntegerobjectObjectobject[]Object[]mapMaphashmapHashMaplistListarraylistArrayListcollectionCollection
如果类没有别名则需要使用全限定符或自定义别名
自定义别名方法typeAliases标签写在settings标签下
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置意在降低冗余的全限定类名书写。例如
typeAliasestypeAlias aliasAuthor typedomain.blog.Author/typeAlias aliasBlog typedomain.blog.Blog/
/typeAliases当这样配置时Blog 可以用在任何使用 domain.blog.Blog 的地方。
也可以指定一个包名MyBatis 会在包名下面搜索需要的 Java Bean比如
typeAliases package namedomain.blog/ /typeAliases每一个在包 domain.blog 中的 Java Bean在没有Alias注解的情况下会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author若有Alias注解则别名为其注解指定的值。见下面的例子
Alias(author)
public class Author {...
}单个实体类型
!--返回单个自定义实体类型--
select idqueryById resultTypecom.ergou.pojo.EmployeeSELECT emp_id empId,emp_name empName,emp_salary empSalaryFROM t_emp WHERE emp_id ${id}/select默认要求返回单个实体类型时列名和属性名要对应且一致才能进行实体类的属性映射
也可以进行设置在mybatis-config.xml文件中进行设置支持驼峰式自动映射即自动将下划线格式转化为驼峰格式例将emp_id转化为empId
!-- 在全局范围内对Mybatis进行配置 --
settings!-- 具体配置 --!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 --!-- 将mapUnderscoreToCamelCase属性配置为true表示开启自动映射驼峰式命名规则 --!-- 规则要求数据库表字段命名方式单词_单词 --!-- 规则要求Java实体类属性名命名方式首字母小写的驼峰式命名 --setting namemapUnderscoreToCamelCase valuetrue//settingsMap类型
适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应没法封装到实体类对象中。能够封装成实体类类型的就不使用Map类型。
!-- MapString,Object selectEmpNameAndMaxSalary(); --
!-- 返回工资最高的员工的姓名和他的工资 --
select idselectEmpNameAndMaxSalary resultTypemapSELECTemp_name 员工姓名,emp_salary 员工工资,(SELECT AVG(emp_salary) FROM t_emp) 部门平均工资FROM t_emp WHERE emp_salary(SELECT MAX(emp_salary) FROM t_emp)
/selectList类型
若返回值是集合resultType不需要指定集合类型只需要指定泛型即可
!-- ListEmployee selectAll(); --
select idselectAll resultTypecom.atguigu.mybatis.entity.Employeeselect emp_id empId,emp_name empName,emp_salary empSalaryfrom t_emp
/select关于主键
自增长主键回显由mysql的auto_increment自动产生的主键值 使用userGeneratedKeys属性将其设置为true 在keyColumn属性中写上主键的列名可省略 在keyProperty属性中指定存储主键的属性名 最终生成的对象会多一个其属性名为keyProperty指定的属性名的属性里面存储着插入对象的的主键值
!-- int insertEmployee(Employee employee); --
!-- useGeneratedKeys属性字面意思就是“使用生成的主键” --
!-- keyProperty属性可以指定主键在实体类对象中对应的属性名Mybatis会将拿到的主键值存入这个属性 --
insert idinsertEmployee useGeneratedKeystrue keyPropertyempIdinsert into t_emp(emp_name,emp_salary)values(#{empName},#{empSalary})
/insert非自增长类型主键的维护不是自动增长的主键值
在insert标签中使用selectKey标签在其中写一段sql语句查询关于select标签
属性 order:sql语句是在插入语句之前还是之后进行resultType返回值类型keyProperty查询结果给哪个属性赋值这个属性可以给insert标签中的sql语句使用同时在生成的相应java对象中也会多一个此属性可以通过get方法获取 实体类属性和数据库字段对应关系
当列名和属性名不一致有以下解决方案
①给查询的列名起别名此别名和属性名一致
②使用驼峰式映射
!-- 使用settings对Mybatis全局进行设置 --
settings!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 --setting namemapUnderscoreToCamelCase valuetrue//settings③resultMap自定义映射
resultType按照规则自动映射按照是否开启驼峰式映射自己映射属性和列名只能映射一层结构即一个对象的属性是其他类的对象该属性的属性不会自动映射
resultMap自定义映射使用resultMap标签result标签就是一个中间处理的标签处理数据库的列名和属性名之间的映射
!-- 专门声明一个resultMap设定column到property之间的对应关系 --
!--属性id供select标签的selectMap属性调用的值--
resultMap idselectEmployeeByRMResultMap typecom.atguigu.mybatis.entity.Employee!-- 使用id标签设置主键列和主键属性之间的对应关系 --!-- column属性用于指定字段名property属性用于指定Java实体类属性名 --id columnemp_id propertyempId/!-- 使用result标签设置普通字段和Java实体类属性之间的关系 --result columnemp_name propertyempName/result columnemp_salary propertyempSalary//resultMap!-- Employee selectEmployeeByRM(Integer empId);
属性改为使用resultMap属性--
select idselectEmployeeByRM resultMapselectEmployeeByRMResultMapselect emp_id,emp_name,emp_salary from t_emp where emp_id#{empId}/selectselect标签中调用了result标签result标签中的type属性指定了返回值类型间接指定了select标签的返回值类型