首页
留言板
友链
关于
Search
1
内测“合金弹头”嘿嘿
757 阅读
2
Nginx搭建一个简易的图床
713 阅读
3
Kettle循环遍历结果集作为参数传入转换
674 阅读
4
Apache Dubbo初步认识
395 阅读
5
给站点添加邮件通知功能
374 阅读
知识库
好奇猫
日常说
笔记本
登录
/
注册
Search
标签搜索
maven
Spring
vue
Java
Java代码
前端
idea
帆软
MySQL
git
CSS
游戏
Bootstrap
生活
网上冲浪
邮件配置
说说
Nginx
Excel
数据库调优
龙流
累计撰写
61
篇文章
累计收到
17
条评论
首页
栏目
知识库
好奇猫
日常说
笔记本
页面
留言板
友链
关于
搜索到
1
篇与
MyBatis
的结果
2022-06-01
MyBatis入门到"入坟"
mybatis它内部封装了jdbc,简化了原始持久层操作每次都要去处理加载驱动、创建连接、创建statement等繁杂的过程;上面这些操作,JDBCTemplate工具类也实现了,为什么JDBCTemplate不叫框架,而是工具类呢?原因是工具类只是对操作的一些封装,对于更多的细节它并没有去处理和提供解决方案。定制化SQL、存储过程、高级映射相较jdbc,SQL代码夹杂在Java代码中耦合度高不易维护相较Hibernate和JPA 自动生成SQL,不容易做特殊优化 反射太多,导致数据库性能下降mybatis的简单搭建打开idea创建一个空的maven项目,导入mybatis和数据库MySQL的maven依赖配置mybatis的配置文件(该配置文件名固定,以便项目启动是能识别找到该配置文件)<?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"> <!-- mybatis的主配置文件 --> <configuration> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql的环境--> <environment id="mysql"> <!-- 配置事务的类型--> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments> <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 --> <mappers> <mapper resource="com/lwlong/dao/IUserDao.xml"/> </mappers> </configuration>顺便配置一下日志# 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:\axis.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创建映射文件mapper<?xml version="1.0" encodeing="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lwlong.dao.IUserDao"> <!--查询所有用户--> <select id="findAll" resultType="com.lwlong.entity.User"> select * from user </select> </mapper>MyBatis的使用案例public static void main(String[] args)throws Exception { //1.读取配置文件 InputStream is = Resource.getResourceAsStream("SqlMapConfig.xml"); //2.创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); //3.使用工厂生产SqlSession对象 SqlSession sqlSession = factory.openSession(); //4.使用SqlSession创建Dao(Mapper)接口的代理对象 IUserDao userDao = sqlSession.getMapper(IUserDao.class); //5.使用代理对象执行方法 List<User> users = userDao.findAll(); for(User user : users) { System.out.println(user); } //6.释放资源 sqlSession.close(); is.close(); }MyBatis细节处理解决方案MyBatis获取参数的几种方式1、通过#{}方式,原理是占位符的形式,可以防止SQL注入,替换的参数默认使用''包围2、通过${}方式,原理字符串拼接形式,存在SQL注入风险,传入的参数是什么就直接替换到SQL语句中3、Mapper的代理实现类,mapper接口方法的参数,底层对传入的参数是以Map的形式封装,默认有键为parma1,parma2 ...;在mapper.xml文件中sql的#{}、${}通过属性名获取,①使用java对象传递,对象的属性;②使用多个参数,mapper接口中参数设置@Param注解value值;③通过位置形式获取;④通过map通过${}方式,动态替换表名在标签中设置useGeneratedKeys="true"开启获取自增的主键,seyProperty="对象属性名"设置回写到对象属性中全局配置处理字段名和属性名不一致的情况在mybatis-config.xml配置文件中添加如下配置<settings> <!--将下划线映射为驼峰-> <setting name="mapUnderscoreTocamelcase" value="true"/> </settings>使用resultMap处理属性名与字段名不一致的情况在Mapper.xml映射SQL字段,使用标签,设置<resultMap id="empResultMap" type="com.xxx.Emp"><!--如果配置了mybatis全局别名配置,可以直接写默认简称别名--> <result property="empId" column="emp_id" jdbcType="int"/> <result property="empName" column="emp_name" jdbcType="String"/> <result property="age" column="age" jdbcType="int"/> </resultMap>也用来处理封装级联对象属性:关联查询中如员工信息关联部门信息,分别封装在对应的实体类中使用association来处理封装级联对象属性<association property="dept" javaType="Dept"> <id column="dept_id" property="deptId"></id> <result column="dept_name" property="deptName"></result> </ association> > MyBatis处理多对一的映射关系查询,使用分步的查询方式;缺点:写的查询语句多;优点:可以延迟加载 > 必须在全局配置文件中设置全局配置信息 > lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载 > aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载 > 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加载)|eager(立即加载)"mybatis动态SQLMybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接sQL语句字符串时的痛点问题。I标签的使用:ifif标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行<!--List<Emp> getEmpListByCondition(Emp emp);--> <select id="getEmpListByMoreT" resultType="Emp"> select * from t_emp where 1=1 <if test="ename != '' and ename != nu11"> and ename = #{ename} </if> <if test="age != '' and age != nu11"> and age = #{age} </if> <if test="sex != '' and sex != nu11"> and sex = #{sex} </if> </select>wherewhere标签,可以自动生成where关键字,可以自动去除条件字段前的and关键字,不能去除条件字段后的and的关键字;trimtrim标签属性prefix、suffix:在标签中内容前面或后面添加指定内容prefixOverrides、suffixOverrides:在标签中内容前面或后面去掉指定内容<select id="getEmpListByMoreT" resultType="Emp"> select * from t_emp <trim prefix="where" suffixoverrides="and"> <if test="ename != '' and ename != nu11"> ename = #{ename} and </if> <if test="age != '' and age != nu11"> age = #{age} and </if> <if test="sex != '' and sex != nu11"> sex = #{sex} and </if> </trim> </select>choose、when、otherwise多条件判断组合标签,相当于java中的if...else if...elseforEach试用在批量添加、批量删除,非常常用的标签<!--void insertMoreEmp(@param ( " emps" ) List<Emp> emps);--> <insert id="insertMoreEmp"> insert into t_emp values <foreach collection="emps" item="emp" separator=","> (null,#{emp. empName} ,#{emp.age} ,#{emp.gender},null) </foreach> </insert> <!--void deleteMoreEmp(@param ( "empIds" ) Integer[] empIds);--> <delete id="deleteMoreEmp"> delete from t_emp where <foreach collection="empIds" item="empId" separator="or"> emp_id = #{empId} </foreach> </delete>sqlsql标签,定义一个sql片段,例如:在mybatis中建议不要写select * ...因为在执行时还是要去查找一遍具有的字段;也可以定义存储过程;<sql id="empcolumns"> emp_id,emp_name,age,gender,dept_id </sql> <!--然后在select标签中,写查询语句时,使用<include refid="片段id">标签引入sql片段--> <select id="getEmpListByMoreT" resultType="Emp"> select <include refid="empcolumns"></include> from t_emp </select>MyBatis的缓存MyBatis的一级缓存(默认开启的)一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问使一级缓存失效的四种情况:|1)不同的SqlSession对应不同的一级缓存2)同一个SqlSession但是查询条件不同3)同一个SqlSession两次查询期间执行了任何一次增删改操作4)同一个SqlSession两次查询期间手动清空了缓存@Test public void testGetEmpById(){ SqlSession sqlSession1 = SqlSessionUtil.getSqlSession(); CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class); Emp emp1 = mapper1.getEmpById(1); System.out.println(emp1); Emp emp2 = mapper1.getEmpById(1); System.out.println(emp2); SqlSession sqlSession2 = SqlSessionUtil.getSqlSession(); CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class); Emp emp3 = mapper2.getEmpById(1); System.out.println(emp3); }MyBatis的二级缓存二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取二级缓存开启的条件:a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置b>在映射文件中设置标签<cache/>c>二级缓存必须在SqlSession关闭或提交之后有效d>查询的数据所转换的实体类类型必须实现序列化的接口使二级缓存失效的情况:两次查询之间执行了任意的增剧改,会使一级和二级缓存同时失效
2022年06月01日
35 阅读
0 评论
0 点赞