南昌网站排名优化软件,广州网站建设新锐,大同滕佳科技网站建设,成都网络推广哪家公司好星光下的赶路人star的个人主页 夏天就是吹拂着不可预期的风 文章目录 1、Mybatis介绍1.1 JDBC痛点1.2 程序员的诉求1.3 Mybatis简介 2、数据准备2.1 数据准备2.2 建工程2.3 Employee类2.4 Mybatis的全局配置2.5 编写要执行的SQL2.6 编写java程序2.7 稍微总结一下流程 3、解决属… 星光下的赶路人star的个人主页 夏天就是吹拂着不可预期的风 文章目录 1、Mybatis介绍1.1 JDBC痛点1.2 程序员的诉求1.3 Mybatis简介 2、数据准备2.1 数据准备2.2 建工程2.3 Employee类2.4 Mybatis的全局配置2.5 编写要执行的SQL2.6 编写java程序2.7 稍微总结一下流程 3、解决属性无法封装的问题4、接口式编程4.1 编写Dao层接口4.2 编写Mapper所使用的SQLEmployeeMapper.xml4.3 接口式编程的使用步骤4.4 测试代码4.5 注解接口式编程 5、ResultMap6、引入Sql模板7、获取接口方法入参8、Sql注入 9、动态SQL 1、Mybatis介绍
MyBatis原名为iBatis是一种开源的持久层框架它简化了在Java应用程序中的数据库访问。MyBatis通过将数据库查询和映射任务从Java代码中分离出来提供了一种灵活且强大的方式来处理数据持久化。
1.1 JDBC痛点 JDBC是Java中对数据库进行读写的标准原生JDBC的痛点在于
SQL夹在Java代码中耦合度高导致每次修改SQL都需要重新测试编译打包部署维护不易。大量冗余的模板代码编写起来费力。
1.2 程序员的诉求
对于开发人员来说我们希望掌握核心科技即SQL是由我们编写的而其他脏活和累活由框架为我们自动完成。 除此之外我们还希望SQL和java代码分离保持低耦合。这样在频繁需要修改SQL的场景下只需要修改SQL语句的编码文件而无需更改java源代码简化部署流程。
1.3 Mybatis简介
MyBatis是一个java编写的轻量级使用方式简单的半自动sql自己写其他框架做的ORM映射的Dao层框架 DaoDataBase Access Object:指java程序中专门用于访问数据库的对象 ORMObject Relation Mapping指将java程序中封装数据的Bean和数据库中的保存数据的表结构进行映射。 ORM的规则中
一种Bean对应一张表Bean的一个属性对应表中的一列一个Bean对应数据库中的一行读数据库即是把表中的行封装为一个Bean写数据库就是把Bean中的属性写入到表中
2、数据准备
以查询数据库中指定id的员工为例
2.1 数据准备
CREATE DATABASE Mybatis CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE TABLE employee(id INT(11) PRIMARY KEY AUTO_INCREMENT,last_name VARCHAR(255),gender VARCHAR(10),email VARCHAR(255)
);
INSERT INTO employee(last_name,gender,email) VALUES(Tom,male,Tom163.com);
INSERT INTO employee(last_name,gender,email) VALUES(Jack,male,Jack163.com);
INSERT INTO employee(last_name,gender,email) VALUES(Marry,female,Tom163.com);2.2 建工程
创建IDEAproject在相关的module的pom中添加如下依赖
dependenciesdependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.4.6/version/dependency!-- mysql数据驱动包 -- dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.27/version/dependency
!-- bean --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.20/versionscopeprovided/scope/dependency
!-- 测试 --dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!-- 打印日志 --dependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version/dependency/dependencies2.3 Employee类
Data
AllArgsConstructor
NoArgsConstructor
public class Employee {private Integer id;private String lastName;private String gender;private String email;}2.4 Mybatis的全局配置
在resources目录下加入MyBatis的全局配置文件根据自己的配置要修改
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationenvironments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://hadoop102:3306/Mybatis?serverTimezoneAsia/Shanghaiamp;useUnicodetrueamp;characterEncodingUTF-8/property nameusername valueroot/property namepassword value000000//dataSource/environment/environments
/configuration2.5 编写要执行的SQL
myba的优点在于java代码和sql语句分离。sql语句编写在xml文件中同时注意需要再全局配置文件中注册 在resources中添加存放sql语句的xml配置文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacegoodselect ida resultTypecom.zhm.mybatis.beans.Employeeselect * from employee where id #{id}/select/mapper之后需要再全局的配置中注册即让MyBatis可以通过指定的xml文件找到辨析的sql。在mybatis.xml的最后位置添加如下内容
mappersmapper resourcesql.xml/
/mappers如果希望在控制台看到发送的sql语句可以在resources下添加log4j.xml文件。内容如下
?xml version1.0 encodingUTF-8 ?
!DOCTYPE log4j:configuration SYSTEM log4j.dtdlog4j:configuration xmlns:log4jhttp://jakarta.apache.org/log4j/appender nameSTDOUT classorg.apache.log4j.ConsoleAppenderparam nameEncoding valueUTF-8 /layout classorg.apache.log4j.PatternLayoutparam nameConversionPattern value%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n //layout/appenderlogger namejava.sqllevel valuedebug //loggerlogger nameorg.apache.ibatislevel valueinfo //loggerrootlevel valuedebug /appender-ref refSTDOUT //root
/log4j:configuration2.6 编写java程序
public class MybatisDemo1
{public static void main(String[] args) throws IOException {//读取配置文件String resource mybatis.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();/*发送sql 查询某个id的员工selectOne(String statement, Object parameter)statement: sql语句。使用 namespace.id的方式来引用parameter 语句中传入的参数*//* Object o sqlSession.selectOne(good.a, inputStream);Employee employee (Employee) o;*/// 泛型方法的调用: 对象.泛型类型方法()Employee employee sqlSession.EmployeeselectOne(good.a, 1);System.out.println(employee);sqlSession.close();}
}运行截图
2.7 稍微总结一下流程
1、首先是要在mysql中有表 2、根据表的信息来创建对应的Bean 3、然后如果没有MyBatis的全局配置就配置一个 4、在resources中编写一个要执行的sql配置文件 5、编写java程序测试能不能从数据库中将数据封装为Bean
3、解决属性无法封装的问题
眼神好的小伙伴应该已经看出我上一步执行的程序是有问题的运行结果中的对象的lastName的值是null但是在数据库中却不是null。
这就是要涉及java的规范和mysql库的规范扯上关系了java的属性一般是驼峰式命名的但是mysql却是下划线作为分隔符的这就会导致java在生成某个属性方法式也是利用驼峰式生成的方法举个例子吧比如Employee中的lastname想要和数据库中的last_name映射上就得设置映射规则 在mybatis.xml中添加如下配置 settingssetting namemapUnderscoreToCamelCase valuetrue//settings注意这个配置是有顺序的比较前 解释配置了这个MyBatis在映射的时候就会把下划线转为驼峰式的映射规则 运行截图
4、接口式编程
使用MyBatis原生API进行开发有以下不便之处
我们更倾向于使用Dao—DaoImpl来分层解耦方法的返回值是Object类型不能直接使用需要强转方法的入参无法进行严格的检查
在此推荐使用接口式编程开发。即在接口中明确Dao层对象方法的参数类型和返回值类型通过接口中的Dao层方法调用SQL。 这对编写SQL的xml文件提出以下硬性要求
namespace:必须和接口的全类名一致sql的id必须和对应的方法名一致select标签中返回值类型和参数类型也必须和对应的方法一致
4.1 编写Dao层接口
Dao层接口在myba中相关称之为Mapper。
public interface EmployeeMapper
{//根据id查询员工Employee getEmpById(Integer id);//根据id删除员工信息void deleteEmpById(Integer id);//新增员工信息void insertEmp(Employee employee);//修改员工信息void updateEmp(Employee employee);//查询所有ListEmployee getAll();
4.2 编写Mapper所使用的SQLEmployeeMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--namespace: 名称空间类似包名。必须和对应的接口的全类名一致
--
mapper namespacecom.atguigu.mybatis.mapper.EmployeeMapper!--定义sql是什么语句就用什么标签。select语句使用 select标签语句标签上的id是这条语句在这个文件中的唯一标识必须保证唯一。要和对应的方法名一致如果是查询语句必须在标签头上声明返回值类型resultType: 查询的结果集中的一行要封装为的Bean的类型--!--字面量字面上就能看出变量值的变量: 基本数据类型及包装类Stringint a 1;double b 2.0d;String s haha;非字面量: Employee e new Employee();关于占位符:在jdbc中使用?作为占位符在mybatis中使用 #{xxx}作为占位符xxx如果传参的方法中传入的参数中只有一个且是普通参数(字面量)xxx可以随便写.如果传参的方法中传入的参数中只有一个且是Beanxxx可以写Bean的属性名#{xxx}就能获取Bean的属性值。--select idgetEmpById resultTypecom.atguigu.mybatis.beans.Employeeinclude refidsql1/ where id #{id}/select!--void updateEmp(new Employee(1, jack, a, b));#{id} 1#{lastName} jack--update idupdateEmpupdate employee set last_name #{lastName} , gender #{gender} ,email #{email}where id #{id}/updateinsert idinsertEmpinsert into employee(last_name,gender,email) values(#{lastName},#{gender},#{email})/insertdelete iddeleteEmpByIddelete from employee where id #{xxxx}/deleteselect idgetAllEmp resultMaprm1select * from employee/select
/mapper编写完之后要在全局的配置文件中注册
mappersmapper resourceEmployeeMapper.xml/
/mappers4.3 接口式编程的使用步骤
SqlSession session sqlSessionFactory.openSession();try {//获取接口的实现EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//进行CRUD} finally {session.close();}SqlSession由于不是线程安全的因此不能作为静态变量或实例变量而应该在每个方法中单独获取并且使用完成之后关闭。不可以在多个方法中共享sqlSession
4.4 测试代码
public class EmployeeMapperTest
{private SqlSessionFactory sqlSessionFactory;{String resource mybatis.xml;InputStream inputStream null;try {inputStream Resources.getResourceAsStream(resource);} catch (IOException e) {throw new RuntimeException(e);}sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);}Testpublic void getAll() {SqlSession session sqlSessionFactory.openSession();try {//com.sun.proxy.$Proxy5 implements com.atguigu.mybatis.mapper.EmployeeMapper//使用Mybatis提供的动态代理技术获取接口的一个实例EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//class com.sun.proxy.$Proxy5System.out.println(mapper.getClass());//[interface com.atguigu.mybatis.mapper.EmployeeMapper]System.out.println(Arrays.toString(mapper.getClass().getInterfaces()));//进行CRUDmapper.getAll().forEach(System.out::println);} finally {session.close();}}
Testpublic void selectOne() {SqlSession session sqlSessionFactory.openSession();try {EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//CRUDEmployee emp mapper.getEmpById(1);System.out.println(emp);} finally {session.close();}}Testpublic void delete() {SqlSession session sqlSessionFactory.openSession(true);try {EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//CRUDmapper.deleteEmpById(1);System.out.println(删除成功);//手动提交事务//session.commit();} finally {session.close();}}Testpublic void update() {SqlSession session sqlSessionFactory.openSession(true);try {EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//CRUDEmployee e mapper.getEmpById(3);e.setLastName(hahaha);e.setEmail(xixixi);mapper.updateEmp(e);} finally {session.close();}}Testpublic void insert() {SqlSession session sqlSessionFactory.openSession(true);try {EmployeeMapper mapper session.getMapper(EmployeeMapper.class);//CRUDmapper.insertEmp(new Employee(null, jack, a, b));} finally {session.close();}}
}
1、获取所有员工测试截图 2、根据id获取员工信息 3、根据id删除员工 4、更新员工信息 5、插入员工信息
4.5 注解接口式编程
如果注重效率也可以直接在Mapper的方法上标注相应的注解从而替代mapper.xml 的效果。
public interface EmployeeMapper2
{//根据id查询员工Select( select * from employee where id #{ageakljga} )Employee getEmpById(Integer id);//增删改 写操作 不需要返回值Delete(delete from employee where id #{xxxx})void deleteEmpById(Integer id);Insert( insert into employee(last_name,gender,email) values(#{lastName},#{gender},#{email})\n)void insertEmp(Employee employee);Update( update employee set last_name #{lastName} , gender #{gender} ,email #{email}\n where id #{id})void updateEmp(Employee employee);Select( select * from employee )ListEmployee getAll();}添加注解之后同样需要再全局配置文件中配置sql语句所在的Mapper接口全类名
mapper classcom.atguigu.mybatis.mapper.EmployeeMapper2/5、ResultMap
当要封装的Bean的属性名和查询的方法无法一样对应时就需要使用resultMap来自定义列名和Bean中字段的映射规则。 例如有如下查询方法
ListEmp getAllEmp();其中查询的Bean结构如下
Data
NoArgsConstructor
AllArgsConstructor
public class Emp
{private Integer id;private String name;private GenderAndEmail genderAndEmail;
}Data
NoArgsConstructor
AllArgsConstructor
public class GenderAndEmail
{private String gender;private String emailAddr;
}此时Bean的字段名与所查询表的相关列名有很大差别。使用resultType直接封装的话有很多字段是无法正常封装的。我们使用resultMap自定义映射规则。 select idgetAllEmp resultMapempMapRuleselect *from employee/selectresultMap idempMapRule typecom.atguigu.mybatis.beans.Emp autoMappingtrueresult propertyname columnlast_name/association propertygenderAndEmail javaTypecom.atguigu.mybatis.beans.GenderAndEmail autoMappingtrueresult propertyemailAddr columnemail//association
/resultMap6、引入Sql模板
在MySQL的Sql配置文件中可以使用标签来定义sql之后使用标签来引入sql这样可以将高频使用的sql模板进行复用。 如下
select idrowsOfTable resultTypeintselect count(*)include refidsql1/
/selectsql idsql1from employee
/sql7、获取接口方法入参
在sql的xml中可以使用${}和#{}来获取方法中传入的参数。 ${参数名}可以直接获取指定参数名的值不做任何处理 一般用与表名传参 #{ 参数名}在获取指定参数后还会对类型进行判断进行相应的处理例如为String类型的参数自动添加引号一般用于参数传参。 在使用Param注解可以在接口方法有多个参数时为参数自定义参数名。
8、Sql注入
sql注入通常指的是恶意利用sql语句拼接的漏洞注入非法的查询条件来非正常获取数据的行为。例如
Select(select * from employee where gender ${gender})
ListEmployee getEmpsByCondition(Param(gender) String gender);此时在调用时模拟sql注入如下:
ListEmployee emps mapper.getEmpsByCondition(male or id 0 );后果是数据库中的所有用户信息都将被非法获取。所以在参数位置我们要尽量避免使用${}而使用#{}
9、动态SQL
有时候我们需要根据前台传入的参数动态的去拼接sql的过滤条件如果使用${}去拼接sql又会面临着sql注入的风险。所以此时可以使用MyBatis的动态sql技术既可以满足拼接sql的需求又可以避免sqk注入的风险。 示例
ListEmployee queryByCondition(Param(name) String name,Param(id) Integer id,
Param(gender) String gender);sql语句如下
select idqueryByCondition resultTypecom.zhm.mybatisplusdemo.beans.Employeeselect*from empwhereif test name ! null and last_name #{name}/ifif test id ! null and id #{id}/ifif test gender ! null and gender #{gender}/if/where
/select其中标签可以在sql中直接生成一个where子句的标识符还可以将where中不符合语法规则部分多余的and或or自动去除。但是需要注意的是必须把and和or编写在语句的前列。 测试观察生成的sql
mapper.queryByCondition(null,null,a))您的支持是我创作的无限动力 希望我能为您的未来尽绵薄之力 如有错误谢谢指正若有收获谢谢赞美