概述
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的ORM持久层框架
MyBatis 消除了几乎所有的 JDBC 代码,参数的手动设置以及结果集的检索
MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录
ORM(Object/Ralational Mapping)即对象/关系映射。是一种数据持久化技术,它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过JavaBean对象去操作数据库表中的数据,不同的持久层框架ORM是不同的
持久化:即把数据保存到可永久保存的存储设备中(如磁盘,数据库等)
持久层:dao/mapper层就是持久层
核心接口和类
每个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心
首先获取SqlSessionFactorBuilder对象,可以根据XML配置文件或Configuration类的实例构建该对象
然后获取SqlSessionFactory对象,该对象实例可以通过SqlSessionFactoryBuilder对象来获得
最后获取SqlSession实例,SqlSession对象中完全包含以数据库为背景的所有执行SQL操作的方法,可以用该实例来直接执行已映射的SQL语句
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder负责构建SqlSessionFactory,并且提供了多个build()方法的重载
配置信息可以以三种形式提供给SqlSessionFactoryBuilder的build()方法,InputStream(字节流)、Reader(字符流)、Configuration(类)
InputStream inputStream= Resources.getResourceAsStream(“mybatis/mybatis.xml”);
SqlSessionFactoryBuilder的最大特点:用过即丢。一旦创SqlSessionFactory对象之后,这个类就不需要存在了,因此SqlSessionFactoryBuilder的最佳范围就是存在于方法体内,也就是局部变量而已
SqlSessionFactory
SqlSessionFactory提供的openSession()方法来获取SqlSession的实例
openSession()方法的参数为boolean值时,若传入为true表示关闭事务控制,自动提交;false表示开始事务控制,若不传参,默认为true
SqlSessionFactory对象一旦创建,就会在整个应用运行过程中始终存在,没有理由去销毁或再创建它,并且再应用运行中也不建议多次创建SqlSessionFactory。因此SqlSessionFactory的最佳作用域是Application,即随着应用的生命周期一同存在,那么这种存在于整个应用运行期间,并且同时只有一个对象实例的模式称之为单例模式
SqlSession
SqlSession是用于执行持久化操作的对象,类似于JDBC中的Connection。它提供了面向数据库执行SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句
SqlSession对应着一次数据库会话。由于数据库会话不是永久的,因此SqlSession的生命周期也不应该是永久的,相反,再每一次访问数据库都需要创建它(这里并不是说SqlSession只能执行一次SQL,SqlSession完全可以执行多次,但是若关闭了SqlSession,那么就需要重新创建它),创建SqlSession的地方只有一个,那就是SqlSessionFactory对象的openSession()方法
每个线程都有自己的SqlSession实例,SqlSession实例不能被共享,也不是线程安全的。因此最佳的作用域范围是request作用域或者方法体作用域内
使用方式
1.通过SqlSession实例来直接执行已映射的SQL语句
2.基于mapper接口方式操作数据
操作步骤
读取配置文件
InputStream inputStream= Resources.getResourceAsStream(“mybatis/mybatis.xml”);
获取一个工厂类
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
获取一个sqlSession会话
SqlSession session = factory.openSession();
获取Mapper的接口对象
接口类型 对象名 = session.getMapper(接口类.class);
调用接口中的方法
事务提交
关闭会话
注释
< select id = " selectUser" resultType = " com.xl.entity.UserEntity" >
SELECT
/* SQL中的注释:采用SQL多行注释 */
id, name, status
FROM
users
select>
MyBatis核心(全局)配置文件(mybatis-config.xml)
MyBatis 的配置文件包含了影响 MyBatis 行为的设置(settings)和属性(properties)信息
:配置文件的根元素节点,子元素需按顺序书写
:配置属性文件
resource属性:外部指定properties属性文件
使用不在一个地方配置执行顺序为
在 properties 元素体内指定的属性首先被读取
然后根据 properties 元素中的 resource 属性读取全类名下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性
最后读取作为方法参数传递的属性,并覆盖已读取的同名属性
:设置MyBatis运行中的全局行为
name:属性名
cacheEnabled:对在此配置文件下的所有cache二级缓存进行全局性开关设置,默认true
lazyLoadingEnabled:全局性设置懒加载,默认true,如果设为fasle,则所有相关联的都会被初始化加载
autoMappingBehavior:MyBatis对于自动映射的匹配级别为 NONE|PARTIAL|FULL
NUNE:禁止自动匹配
PARTIAL:默认。自动匹配所有属性(要求是列名和javaBean属性名一致),有内部嵌套(association,collection)的除外
FULL:自动匹配所有
aggressivelazyLoading:属性按需加载
value:属性值
:为Java类型命名别名(别名处理器)
alias:别名
type:实体类全类名
也可@Alias注解为其指定一个别名
MyBatis已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大写不敏感的,我们在起别名的时候千万不要占用已有的别名
:类型处理器
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型
:插件
插件通过动态代理机制,可以介入四大对象的任何一个方法的执行
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
:配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,该元素节点下可以配置多个environment子元素节点,但是必须指定其中一个默认运行环境(通过default指定)
:配置MyBatis的一套运行环境,
id:指定当前环境的唯一标识
:事务管理
type:MyBatis有两种事物管理类型,即JDBC、MANAGED
设置其属性为JDBC,直接使用JDBC的提交和回滚功能,依赖于从数据源获得来连接来管理事务的生命周期
MANAGED:不提交或回滚一个连接、让容器来管理事务的整个生命周期
可自定义事物管理类型:实现TransactionFactory接口,type=全名/别名
:数据源(库)配置
type:有三种数据源类型(UNPOOLED、POOLED、JNDI)
UNPOOLED:不使用连接池
POOLED:使用连接池
JNDI: 在EJB 或应用服务器这类容器中查找指定的数据源
自定义:实现DataSourceFactory接口,定义数据源的获取方式
:根据不同的数据库厂商执行不同的语句
type:DB_VENDOR //使用MyBatis提供的VendorDatabaseIdProvider解析数据库厂商标识。也可以实现DatabaseIdProvider接口来自定义
会通过 DatabaseMetaData#getDatabaseProductName() 返回的字符串进行设置。由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短
Property-name:数据库厂商标识
Property-value:为标识起一个别名,方便SQL语句使用databaseId属性引用
匹配规则
如果没有配置databaseIdProvider标签,那么databaseId=null
如果配置了databaseIdProvider标签,使用标签配置的name去匹配数据库信息,匹配上设置databaseId=配置指定的值,否则依旧为null
如果databaseId不为null,他只会找到配置databaseId的sql语句
MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库databaseId 属性的所有语句。如果同时找到带有 databaseId 和不带databaseId 的相同语句,则后者会被舍弃
:映射器作用是告诉MyBatis去哪里找到SQL映射文件(该文件内容是开发者定义的映射SQL语句),整个项目可以有一个或多个SQL映射文件
:获取SQL映射文件
resource:使用类资源路径获取资源
class:使用全类名获取,要求接口和映射文件同包同名
url:使用URL获取资源
:批量获取映射文件
name:文件所在包名 //要求接口和映射文件同包同名
SQL映射文件(mapper.xml)
映射文件指导着MyBatis如何进行数据库增删改查
//映射文件的根元素节点,只有一个属性namespace
namespace:用于区分不同的mapper,全局唯一,绑定DAO接口,即面向接口编程。当namespace绑定某一接口之后(一个接口对应一个映射文件),可以不用写该接口的实现类,MyBatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句,因此namespace的属性值必须要和接口同名
//映射插入语句 //映射更新语句 //映射删除语句
id:命名空间的唯一识别符,可以被用来引用这条语句,与接口中的方法名一致
parameterType:参数类型,可不传MyBatis会根据TypeHandler自动推断
flushCache:有语句被调用,会导致本地缓存和二级缓存被清空,默认为true
timeout:在抛出异常前,驱动程序等待数据库返回请求结果的秒数,默认为unset
statementType:默认为PREPARED映射类型,也可设置为STATEMENT映射类型,CALLABLE映射类型
useGeneratedKeys:MyBatis 使用 JDBC 中的 getGeneratedKeys 方法来取出由数据库内部生成的主键(MySQL),默认为false,delete中无效
keyProperty:指定能够唯一识别对象的属性,MyBatis通过getGeneratedKeys方法的返回值或insert语句的selectKey子元素设置它的键值,默认为unset,delete中无效
keyColumn:通过生成的键值设置表中列名,当主键列不是表中的第一列时需设置,在某些数据库(PostgreSQL)是必须的,delete中无效
databaseId:与的value值对应,若配置了databaseIdProvider,MyBatis会加载所有不带databaseId或匹配当前databaseId的语句,如果带或者不带都有,则不带的会被忽略
//为语句传参
KeyProperty:selectKey语句结果应该被设置的目标属性
KeyColumn:匹配属性的返回结果集中的列名称
resultType:结果的类型
order:设置为BEFORE,表示先执行selectKey中的语句,设置为AFTER,表示先执行外层语句
statementType:默认为PREPARED映射类型,也可设置为STATEMENT映射类型,CALLABLE映射类型
#{key}:获取参数的值,预编译到SQL中,安全,类似JDBC的PreparedStatement可防止SQL注入,返回字符串带引号 ‘’
${key}:获取参数的值,拼接到SQL中,有SQL注入问题
//映射查询语句,标签内些查询语句
id:命名空间的唯一识别符,可以被用来引用这条语句
parameterType:参数类型,可不传MyBatis会根据TypeHandler自动推断
resultType:返回值类型,resultType和resultMap不能同时存在,二取其一
resultMap:对外部resultMap的引用,对应外部resultMap的id,表示返回结果映射到哪一个resultMap上,它的应用场景一般是数据库字段与对象属性不一致或者需要做复杂的联合查询以便自由控制映射结果
flushCache:表示任何时候语句被调用,都不会去清空本地缓存和二级缓存,默认为false
useCache:是否开启二级缓存,默认为true
timeout:在抛出异常前,驱动程序等待数据库返回请求结果的秒数,默认为unset
fetchSize:给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值,默认为unset(依赖驱动)
statementType:默认为PREPARED映射类型,也可设置为STATEMENT映射类型,CALLABLE映射类型
resultSetType:FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)
databaseId:与上一个标签databaseId意义相同
resultOrdered:这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false
resultSets:这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔
//导入中的SQL块
//可以重用的SQL块,被其他语句引用(include来引用)
id:引用标识
可为sql语句片段或完整语句,也可为动态sql语句
//用来描述数据库结果集和对象的对应关系
id:中resultMap的id名称
type:需要映射到的类对象
如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)
//将查询结果作为参数注入到实例的构造方法中
//设置主键(可多个)
column:数据表的列,使用{key1=column1,key2=column2…}的形式传递多列数据
property:将column属性指定的列结果映射到对象的哪个属性
javaType:实体类中字段类型
jdbcType:表中字段类型
//配置映射关系
column:数据表的列
property:将column属性指定的列结果映射到对象的哪个属性
javaType:实体类中字段类型
jdbcType:表中字段类型
//处理查询结果中关联其他对象的情况,映射JavaBean的某个复杂类型的属性
fetchType:eager立即加载/lazy延迟加载
columnPrefix:祛除查询结果内列名的指定前缀
javaType:完整的Java类名或者别名,若映射带一个JavaBean,则MyBatis通常会自行检测到其他类型,若映射到一个HashMap,则应该明确指定javaType
嵌套查询方式(分段查询) //指的是通过执行另外一个 SQL 映射语句来返回所关联的对象类型
column:指定数据表的列
property:将column属性指定的列结果映射到对象的哪个属性
select:调用查询当前属性的值
嵌入结果集方式 //指的是通过联表查询将所需的所有字段内容先查询出来,再通过级联属性映射来创建复杂类型的结果对象
property:映射到列结果的字段或属性
javaType:完整的Java类名或者别名
resultMap:引用外部resultMap
//设置主键
//配置映射关系
//处理查询结果中关联其他对象的情况,返回复杂类型的集
fetchType=eager立即加载/lazy延迟加载
嵌套查询方式(分步查询)
column:指定数据表的列
property:映射到列结果的字段或属性
select:调用目标的方法查询当前属性的值
javaType:完整的Java类名或者别名
嵌入结果集方式
column:指定数据表的列
property:映射到列结果的字段或属性
javaType:完整的Java类名或者别名
ofType:完整的Java类名或者别名,即集合中包含的类型(可不写)
//设置主键
//配置映射关系
鉴别器//很像Java语言中的switch 语句,允许用户根据查询结果中指定字段的不同取值来执行不同的映射规则
column:数据表的列
//基于某些值的结果映射
value :查询结果中指定字段的不同取值
resultMap:外部映射规则名
resultType:内部写映射规则
//配置给定命名空间的二级缓存
eviction:缓存的回收策略
LRU – 最近最少使用的:移除最长时间不被使用的对象(默认)
FIFO – 先进先出:按对象进入缓存的顺序来移除它们
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInterval:缓存刷新间隔(缓存多长时间清除一次,默认不清空)毫秒为单位
readOnly:缓存是否只读,默认false
true:MyBatis认为所有从缓存中读取数据库的操作都是只读操作不会修改数据,为加快获取速度,直接会将数据在缓存中的引用交给用户
MyBatis觉得获取的数据可修改,MyBatis会利用序列化&反序列的技术克隆一份新的数据给你
size:缓存存放多少元素
type:指定第三方或自定义缓存的全类名,常见第三方缓存EHCache,Redis,Memcache,需导入jar包与配置文件
//从其它命名空间引入缓存配置
主键生成方式
若数据库支持自动生成主键的字段,则可以设置useGeneratedKeys=”true”,然后再把keyProperty 设置到目标属性上
若数据库不支持自增型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用
参数处理
单个参数
可以接受基本类型,对象类型,集合类型的值。这种情况MyBatis可直接使用这个参数,不需要经过任何处理
多个参数
任意多个参数,都会被MyBatis重新包装成一个Map传入
接口中方法参数只能有一个
parameterType=“Integer[]” 接收数组
使用@Param(“参数名”)为参数命名,key指定
POJO
当这些参数属于我们业务POJO时,我们直接传递POJO
#{}拓展用法:参数也可以指定一个特殊的数据类型
#{property,javaType=double,jdbcType=NUMERIC,numericScale=2}
参数位置支持的属性:javaType、jdbcType、mode(存储过程)、numericScale、resultMap、typeHandler、jdbcTypeName、expression
javaType:通常可以从参数对象中来去确定
jdbcType:通常需要在某种特定的条件下被设置,在我们数据为null的时候,有些数据库可能不能识别myBatis对null的默认处理,比如Oracle
numericScale:设置小数点后保留位数
mode:属性允许指定 IN,OUT 或 INOUT 参数。如果参数为 OUT 或 INOUT,参数对象属性的真实值将会被改变,就像在获取输出参数时所期望的那样
MyBatis两个内置参数
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装成一个map,_parameter就是代表这个map
_databaseId:如果配置了DateBaseIdProvider标签,_databaseId代表当前数据库的别名
动态SQL
动态 SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似
MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作
OGNL对象图导航语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。 类似于EL,SpEL等
访问对象属性:person.name
调用方法:person.getName()
调用静态属性/方法:@java.lang.Math @PI @java.util.UUID @randomUUID()
调用构造方法:new com.bean.Person(‘admin’).name
运算符:+,-*,/,%
逻辑运算符:in,not in,>,>=,<,<=,==,!=
xml中特殊符号如”,>,<等这些都需要使用转义字符
特殊符号 转义字符
& & amp;
< & lt;
> & gt;
" & quot;
' & apos;
a<= b a & lt; = b 或者 a < ! [ CDATA [ <= ] ] > b
a>= b a & gt; = b 或者 a < ! [ CDATA [ >= ] ] > b
a!= b a < ! [ CDATA [ < > ] ] > b 或者 a < ! [ CDATA [ != ] ] > b
简化SQL中的where,如果有条件,条件的第一个and或者or会自动取消,如果无条件,where关键字会取消.
< update id= "updateEmp" >
update tbl_employee
< set>
< if test= "lastName!=null" >
last_name= #{ lastName} ,
< / if >
< if test= "email!=null" >
email= #{ email} ,
< / if >
< if test= "gender!=null" >
gender= #{ gender} ,
< / if >
UPDATE_DATE = SYSDATE
< ! -- set语句之后一定别忘记加逗号-- >
< / set>
where id= #{ id}
< / update>
< select id= "getEmpsByConditionIf" resultType= "com.mybatis.bean.Employee" >
select * from tbl_employee
< where>
< ! --
遇见特殊符号应写转义字符或写在< ! [ CDATA [ ] ] > 区间内(语句前加空格)
-- >
< if test= "id=='0'.toString()" > < ! -- 转换-- >
and id= #{ id}
< / if >
< if test= "lastName!=null && lastName!=""" >
and last_name like #{ lastName}
< / if >
< if test= "email!=null and email.trim()!=""" >
and email= #{ email}
< / if >
< ! -- ognl会进行字符串与数字的转换判断 "0" == 0 -- >
< if test= "gender==0 or gender==1" >
and gender= #{ gender}
< / if >
< / where>
< / select>
,,
< select id= "getEmpsByConditionChoose" resultType= "com.mybatis.bean.Employee" >
select * from tbl_employee
< where>
< ! -- 如果带了id就用id查,如果带了lastName就用lastName查; 只会进入其中一个 -- >
< choose>
< when test= "id!=null" >
id= #{ id}
< / when>
< when test= "lastName!=null" >
last_name like #{ lastName}
< / when>
< when test= "email!=null" >
email = #{ email}
< / when>
< otherwise>
gender = 0
< / otherwise>
< / choose>
< / where>
< / select>
< select id= "getEmpsByConditionTrim" resultType= "com.mybatis.bean.Employee" >
select * from tbl_employee
< ! -- 后面多出的and或者or where标签不能解决
prefix= "" : 前缀:trim标签体中是整个字符串拼串后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides= "" :
前缀覆盖: 去掉整个字符串前面多余的字符
suffix= "" : 后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides= ""
后缀覆盖:去掉整个字符串后面多余的字符
-- >
< ! -- 自定义字符串的截取规则 -- >
< trim prefix= "where" suffixOverrides= "and" >
< if test= "id!=null" >
id= #{ id} and
< / if >
< if test= "lastName!=null && lastName!=""" >
last_name like #{ lastName} and
< / if >
< if test= "email!=null and email.trim()!=""" >
email= #{ email} and
< / if >
< ! -- ognl会进行字符串与数字的转换判断 "0" == 0 -- >
< if test= "gender==0 or gender==1" >
gender= #{ gender}
< / if >
< / trim>
< / select>
< select id= "getEmpsByConditionForeach" resultType= "com.mybatis.bean.Employee" >
select * from tbl_employee
< ! --
collection:指定要遍历的集合:list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator: 每个元素之间的分隔符
open :遍历出所有结果拼接一个开始的字符
close: 遍历出所有结果拼接一个结束的字符
index: 索引。遍历list的时候是index就是索引,item就是当前值
遍历map的时候index表示的就是map的key,item就是map的值
#{ 变量名} 就能取出变量的值也就是当前遍历出的元素
-- >
< foreach collection= "ids" item= "item_id" separator= "," open = "where id in(" close= ")" >
#{ item_id}
< / foreach>
< / select>
示例:
List < ForDownZip > oneDownFun ( List < String > bizKeysList) ;
< foreach collection= "list" item= "bizKeysList" open = "(" separator= "," close= ")" >
#{ bizKeysList}
< / foreach>
List < ForDownZip > oneDownFun ( @Param ( "comCodeList" ) List < String > comCodeList) ;
< foreach collection= "comCodeList" item= "comCode" open = "(" separator= "," close= ")" >
#{ comCode}
< / foreach>
可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值
< select id= "getEmpsTestInnerParameter" resultType= "com.mybatis.bean.Employee" >
< bind name= "_lastName" value= "'%'+lastName+'%'" / >
select * from emp where last_name like #{ _lastName}
< / select>
OGNL 表达式:
e1 or e2
e1 and e2
e1 == e2, e1 eq e2
e1 != e2, e1 neq e2
e1 lt e2:小于
e1 lte e2:小于等于,其他gt(大于), gte(大于等于) 7 e1 in e2
e1 in e2
e1 not in e2
e1 + e2, e1 * e2, e1/ e2, e1 - e2, e1% e2
! e, not e:非,求反
e. method ( args) 调用对象方法
e. property对象属性值
e1[ e2 ] 按索引取值,List , 数组和Map
@class @method ( args) 调用类的静态方法
@class @field 调用类的静态字段值
< ! --
sql片段 解决SQL 中重复的代码冗余,可以提取出来放在sql片段中
1. < sql> 定义sql片段
id 唯一标识
2. < include> 在SQL 中引用SQL 片段片段
refid 需要引用的SQL 片段的id
< property 声明变量, 就可以在SQL 片段中动态调用,让不同的SQL 调用同一个SQL 片段达到不同的功能
name 变量名
value 变量值
一般情况使用${ } 在sql片段中引用. 一单引用了,一定保证每个include都声明了该变量
-- >
< sql id= "selectEmp" >
select ${ columns} from emp
< / sql>
< select id= "QueryEmp4" resultType= "Emp" >
< include refid= "selectEmp" >
< property name= "columns" value= "*" > < / property>
< / include>
< / select>
缓存机制
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制,缓存可以极大的提升查询效率
MyBatis系统中默认定义了两级缓存
默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启
二级缓存需要手动开启和配置,它是基于namespace级别的缓存,如果对表的操作查询可能有牵扯到多个namespace,那么得到的数据就可能是错误的
为了提高扩展性,MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存
一级缓存
一级缓存(local cache)即本地缓存, 作用域默认为sqlSession
当 Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空
当表数据进行DML操作的时,缓存数据也会清空
一级缓存不能被关闭, 但可以调用 sqlSession.clearCache() 来清空本地缓存, 或者改变缓存的作用域
不同的sqlSession具有不同的缓存区域,即不同作用域的缓存互不影响
在mybatis3.1之后, 可以配置本地缓存的作用域
localCacheScope:默认为SESSION,缓存一个会话下执行的所有查询,设置为STATEMENT,可以禁用一级缓存
二级缓存
二级缓存(second level cache)即全局作用域缓存,二级缓存默认不开启,需要手动配置
二级缓存要求POJO实现Serializable接口
二级缓存在 SqlSession 关闭或提交之后才会生效
不同 SqlSession 之间,同一个Mapper数据共享
打开二级缓存
工作机制
一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中
如果会话关闭,一级缓存中的数据就会被保存在二级缓存中,新的会话查询信息,就可以参照二级缓存中的内容
不同namespace查春的数据会放在自己对应的map(缓存)中 查出的数据都会被默认先放在一级缓存中,只有会话提交或者关闭之后,一级缓存的数据才会转移到二级缓存中
缓存命中率
命中率的取值范围 [0.1),衡量查询性能的重要参数
命中率=命中个数/(命中的数+脱靶的数)
用了缓存后会增加查询的效率,但是会降低增删改的效率
第一次查询:无缓存,脱靶+1,总数+1、第二次查询:有缓存,命中+1,总数+1
MyBatis-Spring整合
整合关键配置:将MyBatis-config.xml的配置整合到Spring的配置文件中
< context: property- placeholder location= "classpath:conf/*.properties" system- properties- mode= "NEVER" / >
< bean id= "dataSource" class = "com.alibaba.druid.pool.DruidDataSource" destroy- method= "close" >
< property name= "driverClassName" value= "${mysql.driverName}" > < / property>
< property name= "url" value= "${mysql.url}" > < / property>
< property name= "username" value= "${mysql.username}" > < / property>
< property name= "password" value= "${mysql.password}" > < / property>
< / bean>
< bean id= "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" >
< ! -- 指定mybatis全局配置文件位置 -- >
< property name= "configLocation" value= "classpath:mybatis/mybatis-config.xml" > < / property>
< ! -- 指定数据源 -- >
< property name= "dataSource" ref= "dataSource" > < / property>
< ! -- mapperLocations:所有sql映射文件所在的位置 -- >
< property name= "mapperLocations" value= "classpath:mybatis/mapper/*.xml" > < / property>
< ! -- typeAliasesPackage:批量别名处理-- >
< property name= "typeAliasesPackage" value= "com.gc.bean" > < / property>
< / bean>
< ! -- 自动的扫描所有的mapper的实现并加入到ioc容器中 -- >
< bean id= "configure" class = "org.mybatis.spring.mapper.MapperScannerConfigurer" >
< ! -- 调用的sqlSessionFactory, 这里是String 类型,可省略 -- >
< property name= "sqlSessionFactoryBeanName" value= "sqlSessionFactory" > < / property>
< ! – basePackage: 指定包下所有的mapper接口实现自动扫描并加入到ioc容器中 -- >
< property name= "basePackage" value= "com.gc.dao" > < / property>
< / bean>
MyBatis-逆向工程
MyBatis Generator简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查,以及QBC风格的条件查询。但多表连接、存储过程等这些复杂sql的定义需要我们手工编写
使用步骤
编写MBG的配置文件
配置数据库连接信息
配置javaBean的生成策略
配置sql映射文件生成策略
配置Mapper接口的生成策略
配置要逆向解析的数据表
运行代码生成器生成代码
注:Context标签
targetRuntime=“MyBatis3“可以生成带条件的增删改查
targetRuntime=“MyBatis3Simple“可以生成基本的增删改查
如果再次生成,建议将之前生成的数据删除,避免xml向后追加内容出现的问题
MBG配置文件
< ? xml version= "1.0" encoding= "UTF-8" ? >
< ! DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
< generatorConfiguration>
< context id= "Tables" targetRuntime= "MyBatis" >
< commentGenerator>
< ! -- 是否去除自动生成的注释 true :是 : false : 否 -- >
< property name= "suppressAllComments" value= "true" / >
< / commentGenerator>
< jdbcConnection driverClass= "com.mysql.jdbc.Driver" connectionURL= "jdbc:mysql://localhost:3306/test" userId= "root" password= "123456" >
< / jdbcConnection>
< ! -- 默认false ,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer ,为 true 时把JDBC DECIMAL 和 NUMERIC 类型解析为java. math. BigDecimal -- >
< javaTypeResolver>
< property name= "forceBigDecimals" value= "false" / >
< / javaTypeResolver>
< javaModelGenerator targetPackage= "com.gc.bean" targetProject= ".\src" >
< ! -- enableSubPackages: 是否让schema作为包的后缀 -- >
< property name= "enableSubPackages" value= "true" / >
< ! -- 从数据库返回的值被清理前后的空格 -- >
< property name= "trimStrings" value= "true" / >
< / javaModelGenerator>
< sqlMapGenerator targetPackage= "com.gc.mapper" targetProject= ".\conf" >
< ! -- enableSubPackages: 是否让schema作为包的后缀 -- >
< property name= "enableSubPackages" value= "false" / >
< / sqlMapGenerator>
< javaClientGenerator type= "XMLMAPPER" targetPackage= "com.gc.mapper" targetProject= ".\src" >
< property name= "enableSubPackages" value= "false" / >
< / javaClientGenerator>
< table tableName= "books" domainObjectName= "Book" > < / table>
< table tableName= "dept" schema= "" enableCountByExample= "false"
enableDeleteByExample= "false" enableUpdateByExample= "false"
enableSelectByExample= "false" selectByExampleQueryId= "false" > < / table>
< / context>
< / generatorConfiguration>
public static void main ( String [ ] args) throws Exception {
List < String > warnings = new ArrayList < String > ( ) ;
boolean overwrite = true ;
File configFile = new File ( "MBG配置文件.xml" ) ;
ConfigurationParser cp = new ConfigurationParser ( warnings) ;
Configuration config = cp. parseConfiguration ( configFile) ;
DefaultShellCallback callback = new DefaultShellCallback ( overwrite) ;
MyBatisGenerator myBatisGenerator = new MyBatisGenerator ( config, callback, warnings) ;
myBatisGenerator. generate ( null ) ;
}
@Test
public void test01 ( ) {
SqlSession openSession = build. openSession ( ) ;
DeptMapper mapper = openSession. getMapper ( DeptMapper . class ) ;
DeptExample example = new DeptExample ( ) ;
Criteria criteria = example. createCriteria ( ) ;
criteria. andDeptnameLike ( "%部%" ) ;
criteria. andIdGreaterThan ( 2 ) ;
List < Dept > list = mapper. selectByExample ( example) ;
for ( Dept dept : list) {
System . out. println ( dept) ;
} }
MyBatis-插件开发
MyBatis在四大对象的创建过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象执行目标方法之前进行拦截的效果
MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用
默认情况下,MyBatis 允许使用插件来拦截的方法调用包括
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
pageHelper分页插件
导包(jsqlparser-1.1.jar,pagehelper-5.1.2.jar)
在全局配置文件中注册
< plugins>
< plugin interceptor= "com.github.pagehelper.PageInterceptor" >
< ! -- 针对的数据库 -- >
< property name= "helperDialect" value= "mysql" / >
< ! -- 分页合理化 低于1 页面, 高于最后一页如何处理 -- >
< property name= "reasonable" value= "true" / >
< ! -- 查询没有数据时的处理 -- >
< property name= "pageSizeZero" value= "true" / >
< / plugin>
< / plugins>
PageHelper.startPage(curPage, pageSize); 放在查询之前,PageInfo info=new PageInfo(list);放在查询之后,不能有其他语句
开发步骤
编写插件实现Interceptor接口,并使用@Intercepts注解完成插件签名
@Intercepts ( {
@Signature ( type= StatementHandler . class , method= "parameterize" , args= java. sql. Statement. class )
} )
public class MyFirstPlugin implements Interceptor { }
< plugins>
< plugin interceptor= "com.mybatis.dao.MyFirstPlugin" >
< property name= "username" value= "root" / >
< property name= "password" value= "123456" / >
< / plugin>
< plugin interceptor= "com.atguigu.mybatis.dao.MySecondPlugin" >
< / plugin>
< / plugins>
插件原理
按照插件注解声明,按照插件配置顺序调用插件plugin方法,生成被拦截对象的动态代理
多个插件依次生成目标对象的代理对象,层层包裹,先声明的先包裹;形成代理链
目标方法执行时依次从外到内执行插件的intercept方法
多个插件情况下,我们往往需要在某个插件中分离出目标对象。可以借助MyBatis提供的SystemMetaObject类来进行获取最后一层的h以及target属性的值
Interceptor接口
public Object intercept(Invocation invocation) throws Throwable //拦截目标方法执行
public Object plugin(Object target) //生成动态代理对象,可以使用MyBatis提 供的Plugin类的wrap方法
public void setProperties(Properties properties) //注入插件配置时设置的属性
从代理链中分离真实被代理对象
MetaObject metaObject = SystemMetaObject . forObject ( target) ;
while ( metaObject. hasGetter ( "h" ) ) {
Object h = metaObject. getValue ( "h" ) ;
metaObject = SystemMetaObject . forObject ( h) ;
}
Object obj = metaObject. getValue ( "target" ) ;
MetaObject forObject = SystemMetaObject . forObject ( obj) ;
你可能感兴趣的:(java框架,mybatis)
2025最新Mybatis-plus教程(二)
三、CRUD(一)BaseMapper接口方法介绍BaseMapper中提供了crud方法,具体方法如下://插入一条记录intinsert(Tentity);//根据entity条件,删除记录intdelete(@Param(Constants.WRAPPER)Wrapperwrapper);//删除(根据ID批量删除)intdeleteBatchIds(@Param(Constants.COL
2025最新Mybatis-plus教程(四)
五、MyBatis-Plus的service封装(一)通用Service简介MyBatis-Plus除了通用的Mapper还有通用的Service层,这也减少了相对应的代码工作量,把通用的接口提取到公共。其实按照mp的这种思想,可以自己也实现一些通用的Controller。(二)通用Service方法介绍/***插入一条记录(选择字段,策略插入)**@paramentity实体对象*/defaul
2025最新Mybatis-plus教程(三)
四、MyBatis-Plus条件构造器(一)条件构造器介绍在MyBatis-Plus中提了构造条件的类Wrapper,它可以根据自己的意图定义我们需要的条件。Wrapper是一个抽象类,一般情况下我们用它的子类QueryWrapper来实现自定义条件查询。(二)selectOne方法@TestpublicvoidtestSelectOne(){ QueryWrapperqueryWrapper=n
Java 代理机制详解:从静态代理到动态代理,彻底掌握代理模式的原理与实战
大葱白菜
java合集 java 开发语言 后端 个人开发 学习 代理模式
作为一名Java开发工程师,你一定在使用Spring、MyBatis、RPC框架等技术时接触过“代理”(Proxy)这个概念。无论是Spring的AOP(面向切面编程)、事务管理,还是远程调用、日志记录、权限控制等场景,代理机制都扮演着至关重要的角色。本文将带你全面掌握:什么是代理?静态代理与动态代理的区别JDK动态代理与CGLIB动态代理的实现原理代理模式的典型应用场景代理在主流框架中的使用(如
Java朴实无华按天计划从入门到实战(强化速战版-66天)
岫珩
Java 后端 java 开发语言 学习 Java 时间安排 学习计划
致敬读者感谢阅读笑口常开生日快乐⬛早点睡觉博主相关博主信息博客首页专栏推荐活动信息文章目录Java朴实无华按天计划从入门到实战(强化速战版-66天)1.基础(18)1.1JavaSE核心(5天)1.2数据库与SQL(5天)1.3前端基础(8天)2.进阶(17天)2.1JavaWeb核心(5天)2.2Mybatis与Spring全家桶(6天)2.3中间件入门(4天)2.4实践项目(2天)3.高阶(1
Mybatisplus的雪花算法及代码生成器的使用
你我约定有三
算法 dreamweaver
1.雪花算法1.1背景:雪花算法(Snowflake)的使用背景主要源于高并发分布式系统环境下对唯一ID生成的需求。这种需求在像Twitter这样的社交媒体平台上尤为突出,因为Twitter需要处理每秒上万条消息的请求,并且每条消息都必须分配一个唯一的ID。这些ID不仅需要全局唯一,以跨机器、跨时间区分,还需要保持一定的顺序性(尽管不要求连续),以方便客户端排序和后续的数据处理。1.2与自动递增的
并发编程与MyBatis精髓
AIHacksCash
Java场景面试宝典 Concurrency Java Database Framework
我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、Spri
mybatis的insert(pojo),会返回pojo吗
在MyBatis中,执行insert操作时,Mapper接口的insert方法本身不会直接返回一个包含数据库生成字段的POJO对象。其默认返回值是受影响的数据库行数(通常是int或Integer)。以下是具体分析和解决方案:1.默认行为返回值类型:insert方法返回的是受影响的行数(整数),不是插入后的POJO对象。POJO状态:执行插入后,如果数据库生成了自增ID或其他字段(如创建时间),PO
MyBatis与MyBatis-Plus批量插入实战指南
代码小侦探
mybatis
在实际项目中,批量插入数据是一个常见且重要的需求。本文将详细总结MyBatis和MyBatis-Plus常用的几种批量插入方式,并通过实际代码示例和运行结果,帮助大家更好地理解和应用。一、准备工作导入pom.xml依赖mysqlmysql-connector-javaruntimeorg.mybatis.spring.bootmybatis-spring-boot-starter2.2.2com.
Spring Boot与MyBatis完美融合:整合实战指南
目录1、梳理整合思路2、整合实现2.1环境搭建2.2案例3、整合mybatis-plus报错1.依赖问题2.配置问题3.Mapper接口与XML文件问题4.实体类问题5.数据库连接问题6.SQL语句问题7.Spring容器问题8.其他1、梳理整合思路将MyBatis的DataSource交给SpringIoC容器创建并管理,使用第三方数据库连接池(Druid,C3P0等)代替MyBatis内置的数
MyBatis中#{}与${}的实战避坑指南
MyBatis在持久层框架中占据举足轻重的地位,其映射文件中的两种参数占位符——#{}与${}——常常令初学者困惑,也令资深开发者反复斟酌。笔者在日常代码审计与性能调优过程中,屡次遇到因二者混用而导致的生产事故,因此决定撰写一篇技术博客,结合真实项目片段,系统梳理二者的使用差异、安全边界与工程落地细节。全文约三千字,力求言必有据,例证皆来自可运行的源码仓库,读者可直接复现并验证。在MyBatis的
AI-调查研究-26-【时间管理】全球不同人群社交媒体使用时间情况
武子康
AI DeepSearch 人工智能 ai 学习 职场和发展 职场发展 个人开发 程序人生
点一下关注吧!!!非常感谢!!持续更新!!!AI篇持续更新中!(长期更新)AI炼丹日志-29-字节跳动DeerFlow深度研究框斜体样式架私有部署测试上手架构研究,持续打造实用AI工具指南!Java篇正式开启!(300篇)目前2025年07月10日更新到:Java-68深入浅出分布式服务Netty实现自定义RPC附详细代码MyBatis已完结,Spring已完结,Nginx已完结,Tomcat已完
【Spring Boot 整合 MyBatis 详细教程】
打会游戏睡会觉
spring boot spring boot mybatis 后端
文章目录SpringBoot整合MyBatis详细教程简介环境准备项目搭建项目结构配置项目1.`pom.xml`配置2.`数据源和MyBatis`配置3.`启动类`配置4.`Mapper接口`和`XML映射文件`测试总结SpringBoot整合MyBatis详细教程简介SpringBoot与MyBatis的整合可以让你轻松地构建数据访问层,通过简化配置和自动配置功能,使得开发者可以更加专注于业务逻
Spring Boot 整合 MyBatis 全流程指南
目录SpringBoot整合MyBatis全流程指南一、整合回顾与准备(一)Spring整合MyBatis回顾(二)SpringBoot整合MyBatis优势(三)案例需求(四)准备数据库二、创建工程并引入依赖三、配置数据源信息四、编写代码(一)引入实体类(二)创建mapper接口(三)创建service接口及实现类(四)创建controller类五、测试工程在实际开发中,配置文件的使用至关重要。
并发编程与MyBatis核心知识
我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)、《解密程序员的思维密码——沟通、演讲、思考的实践》作者、清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。拥有多年一线研发和团队
Java+Vue 地下停车场管理系统的设计与实现
不若浮生一梦
计算机毕设 java vue.js 开发语言
一、项目简介本项目是一款基于SpringBoot+Vue开发的地下停车场管理系统,采用前后端分离架构,后端使用MyBatis操作MySQL数据库,前端使用Vue进行页面展示和用户交互。系统涵盖车位监控、车辆登记、订单生成与结算、在线支付、公告通知、留言反馈、用户积分管理等模块,支持用户端和管理员端的全流程停车管理,适用于中小型停车场数字化转型。项目定位:提升停车场管理效率与用户体验,实现“高效停车
SSM+Vue共享充电宝管理系统 充电宝投放管理系统 共享充电宝维护管理系统Java
计算机程序老哥
作者主页:计算机毕业设计老哥有问题可以主页问我一、开发介绍1.1开发环境开发语言:Java数据库:MySQL系统架构:B/S后端:SSM(Spring+SpringMVC+Mybatis)前端:Vue工具:IDEA或者Eclipse,JDK1.8,Maven二、系统介绍2.1图片展示注册登录页面:登陆前端页面功能:首页、合作商户、充电宝投放、公告栏、个人中心、后台管理首页.png充电宝投放.png
MyBatisPlus 批量添加
文章目录现状优化效果报错现状一般来说,批量插入可以使用MyBatisPlus中ServiceImpl自带的方法saveBatch打开sql日志,application.yml添加配置,mapper-locations配置mapper路径mybatis-plus:configuration:log-impl:org.apache.ibatis.logging.stdout.StdOutImpl#开启
springboot + mybatis使用xml方式九
AmeeLove
springboot集成mybatis使用xml方式依赖org.springframework.bootspring-boot-starter-parent1.5.12.RELEASEorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtestorg.sprin
【经验分享】如何找到适合初学者的Java项目案例?
Java项目开发案例全程实录涉及从需求分析到部署维护的全流程,结合实战经验总结如下关键步骤:项目规划与需求分析:明确业务需求,定义功能范围和用户故事,如电商项目涉及订单处理和库存管理15。系统设计与技术选型:基于需求选择框架和技术栈,例如使用SpringBoot构建微服务架构,MyBatis处理数据交互,Redis作为缓存层优化性能5。编码实现与核心功能开发:业务逻辑层:编写核
狂神说Linux笔记
是你牛天成
项目部署 linux
B站视频狂神说LinuxJava开发之路:JavaSE,MySQL,前端(html,css,js),javaweb,SSM框架,SpringBootvue,SpringCloud,(mybatis-plusgit)LinuxLinux操作系统:Window、Mac消息队列(Kafka,RabbitMQ,RockeetMQ)缓存(Redis)搜索引擎(ElasticSearch)集群分布式(需要购买
MyBatis Plus 中的条件构造器
中东大鹅
mybatis spring boot 后端 java
一、WrapperWrapper:条件构造抽象类,最顶端父类AbstractWrapper:用于查询条件封装,生成sql的where条件QueryWrapper:查询条件封装UpdateWrapper:Update条件封装AbstractLambdaWrapper:使用Lambda语法LambdaQueryWrapper:用于Lambda语法使用的查询WrapperLambdaUpdateWrap
MyBatis Plus 分页
中东大鹅
mybatis java 数据库 spring boot
一、分页插件MyBatisPlus自带分页插件,只要简单的配置即可实现分页功能1、添加配置类@ConfigurationpublicclassMyConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();
MyBatis Plus 对数据表常用注解
中东大鹅
mybatis oracle 数据库 spring boot
1.@TableName(1)解释说明@TableName注解用于指定实体类对应的数据库表名,当实体类的名称与数据库表名不一致时,可以用此注解进行映射。此外,@TableName还支持设置一些其他的配置选项,比如全局表名前缀、后缀的处理。value:指定数据库表名。如果没有设置此注解,则会默认映射到与类名相同的表名。schema:指定数据库的schema,适用于多schema的情况。(2)应用示例
Postgresql数据库Java中mybatis问题记录
haokan_Jia
postgresql JAVA 数据库 postgresql java
项目场景:Java中使用mybatis进行数据查询,使用实体类接收报错“Errorattemptingtogetcolumn‘basin_code’fromresultset.Cause:org.postgresql.util.PSQLException:不良的类型值long:WFG_1\n;不良的类型值long:WFG_1;nestedexceptionisorg.postgresql.util
基于ssm框架的管理系统如何开题,有哪些步骤,怎么设计更合理
勤劳的史蒂夫
1、SSM框架简介SSM框架是SpringMVC,Spring和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为View层,Controller层,Service层,DAO层四层,使用SpringMVC负责请求的转发和视图管理,Spring实现业务对象管理,Mybatis作为数据对象的持久化引擎。DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。D
Day20: Spring与MyBatis的量子纠缠 —— 解密Mapper接口如何获得魔法实现的终极指南
zhysunny
Spring spring mybatis java
目录灵魂拷问时刻:一、Mapper接口的"借尸还魂"术——MapperFactoryBean解剖室1.1Mapper的诞生时刻轴1.2MapperFactoryBean的克隆工厂源码级实例生成流程:1.3接口炼金术——MyBatisProxyFactory核心代码关键对象关系图:二、线程安全防御体系——SqlSessionTemplate的奥秘2.1传统SqlSession的危险性2.2Sprin
[附源码]java毕业设计篮球俱乐部管理系统
卓杰计算机程序设计
java 开发语言 mysql
项目运行环境配置:Jdk1.8+Tomcat7.0+Mysql+HBuilderX(Webstorm也行)+Eclispe(IntelliJIDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:SSM+mybatis+Maven+Vue等等组成,B/S模式+Maven管理等等。环境需要1.运行环境:最好是javajdk1.8,我们在这个平台上运行的。其他版本理论上也可以。2.ID
数据封装、参数接收、日志技术
数据封装Mybatis默认数据封装规则:实体类属性名和数据库表的字段名一致,mybatis会自动封装如果字段名和实体类属性名不一致解决办法:1).手动结果映射在DeptMapper接口方法上,通过@Results及@Result进行手动结果映射。@Results({@Result(column="create_time",property="createTime"),@Result(column=
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
JAVA图文短视频交友+自营商城系统:社交电商新生态的技术实践一、市场需求与技术定位2025年社交电商市场规模突破3.2万亿,用户需求从“单纯购物”转向“社交+消费”融合体验。JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5应运而生,以SpringBoot+MyBatisPlus+MySQL为后端核心,Uniapp(Vue语法)实现跨端兼容,Vue+ElementU
矩阵求逆(JAVA)初等行变换
qiuwanchi
矩阵求逆(JAVA)
package gaodai.matrix;
import gaodai.determinant.DeterminantCalculation;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* 矩阵求逆(初等行变换)
* @author 邱万迟
*
JDK timer
antlove
java jdk schedule code timer
1.java.util.Timer.schedule(TimerTask task, long delay):多长时间(毫秒)后执行任务
2.java.util.Timer.schedule(TimerTask task, Date time):设定某个时间执行任务
3.java.util.Timer.schedule(TimerTask task, long delay,longperiod
JVM调优总结 -Xms -Xmx -Xmn -Xss
coder_xpf
jvm 应用服务器
堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
典型设置:
java -Xmx
JDBC连接数据库
Array_06
jdbc
package Util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtil {
//完
Unsupported major.minor version 51.0(jdk版本错误)
oloz
java
java.lang.UnsupportedClassVersionError: cn/support/cache/CacheType : Unsupported major.minor version 51.0 (unable to load class cn.support.cache.CacheType)
at org.apache.catalina.loader.WebappClassL
用多个线程处理1个List集合
362217990
多线程 thread list 集合
昨天发了一个提问,启动5个线程将一个List中的内容,然后将5个线程的内容拼接起来,由于时间比较急迫,自己就写了一个Demo,希望对菜鸟有参考意义。。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public c
JSP简单访问数据库
香水浓
sql mysql jsp
学习使用javaBean,代码很烂,仅为留个脚印
public class DBHelper {
private String driverName;
private String url;
private String user;
private String password;
private Connection connection;
privat
Flex4中使用组件添加柱状图、饼状图等图表
AdyZhang
Flex
1.添加一个最简单的柱状图
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<?xml version=
"1.0"&n
Android 5.0 - ProgressBar 进度条无法展示到按钮的前面
aijuans
android
在低于SDK < 21 的版本中,ProgressBar 可以展示到按钮前面,并且为之在按钮的中间,但是切换到android 5.0后进度条ProgressBar 展示顺序变化了,按钮再前面,ProgressBar 在后面了我的xml配置文件如下:
[html]
view plain
copy
<RelativeLa
查询汇总的sql
baalwolf
sql
select list.listname, list.createtime,listcount from dream_list as list , (select listid,count(listid) as listcount from dream_list_user group by listid order by count(
Linux du命令和df命令区别
BigBird2012
linux
1,两者区别
du,disk usage,是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和。
AngularJS中的$apply,用还是不用?
bijian1013
JavaScript AngularJS $apply
在AngularJS开发中,何时应该调用$scope.$apply(),何时不应该调用。下面我们透彻地解释这个问题。
但是首先,让我们把$apply转换成一种简化的形式。
scope.$apply就像一个懒惰的工人。它需要按照命
[Zookeeper学习笔记十]Zookeeper源代码分析之ClientCnxn数据序列化和反序列化
bit1129
zookeeper
ClientCnxn是Zookeeper客户端和Zookeeper服务器端进行通信和事件通知处理的主要类,它内部包含两个类,1. SendThread 2. EventThread, SendThread负责客户端和服务器端的数据通信,也包括事件信息的传输,EventThread主要在客户端回调注册的Watchers进行通知处理
ClientCnxn构造方法
&
【Java命令一】jmap
bit1129
Java命令
jmap命令的用法:
[hadoop@hadoop sbin]$ jmap
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a
Apache 服务器安全防护及实战
ronin47
此文转自IBM.
Apache 服务简介
Web 服务器也称为 WWW 服务器或 HTTP 服务器 (HTTP Server),它是 Internet 上最常见也是使用最频繁的服务器之一,Web 服务器能够为用户提供网页浏览、论坛访问等等服务。
由于用户在通过 Web 浏览器访问信息资源的过程中,无须再关心一些技术性的细节,而且界面非常友好,因而 Web 在 Internet 上一推出就得到
unity 3d实例化位置出现布置?
brotherlamp
unity教程 unity unity资料 unity视频 unity自学
问:unity 3d实例化位置出现布置?
答:实例化的同时就可以指定被实例化的物体的位置,即 position
Instantiate (original : Object, position : Vector3, rotation : Quaternion) : Object
这样你不需要再用Transform.Position了,
如果你省略了第二个参数(
《重构,改善现有代码的设计》第八章 Duplicate Observed Data
bylijinnan
java 重构
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusE
struts2更改struts.xml配置目录
chiangfai
struts.xml
struts2默认是读取classes目录下的配置文件,要更改配置文件目录,比如放在WEB-INF下,路径应该写成../struts.xml(非/WEB-INF/struts.xml)
web.xml文件修改如下:
<filter>
<filter-name>struts2</filter-name>
<filter-class&g
redis做缓存时的一点优化
chenchao051
redis hadoop pipeline
最近集群上有个job,其中需要短时间内频繁访问缓存,大概7亿多次。我这边的缓存是使用redis来做的,问题就来了。
首先,redis中存的是普通kv,没有考虑使用hash等解结构,那么以为着这个job需要访问7亿多次redis,导致效率低,且出现很多redi
mysql导出数据不输出标题行
daizj
mysql 数据导出 去掉第一行 去掉标题
当想使用数据库中的某些数据,想将其导入到文件中,而想去掉第一行的标题是可以加上-N参数
如通过下面命令导出数据:
mysql -uuserName -ppasswd -hhost -Pport -Ddatabase -e " select * from tableName" > exportResult.txt
结果为:
studentid
phpexcel导出excel表简单入门示例
dcj3sjt126com
PHP Excel phpexcel
先下载PHPEXCEL类文件,放在class目录下面,然后新建一个index.php文件,内容如下
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
if (PHP_SAPI == 'cli')
die('
爱情格言
dcj3sjt126com
格言
1) I love you not because of who you are, but because of who I am when I am with you. 我爱你,不是因为你是一个怎样的人,而是因为我喜欢与你在一起时的感觉。 2) No man or woman is worth your tears, and the one who is, won‘t
转 Activity 详解——Activity文档翻译
e200702084
android UI sqlite 配置管理 网络应用
activity 展现在用户面前的经常是全屏窗口,你也可以将 activity 作为浮动窗口来使用(使用设置了 windowIsFloating 的主题),或者嵌入到其他的 activity (使用 ActivityGroup )中。 当用户离开 activity 时你可以在 onPause() 进行相应的操作 。更重要的是,用户做的任何改变都应该在该点上提交 ( 经常提交到 ContentPro
win7安装MongoDB服务
geeksun
mongodb
1. 下载MongoDB的windows版本:mongodb-win32-x86_64-2008plus-ssl-3.0.4.zip,Linux版本也在这里下载,下载地址: http://www.mongodb.org/downloads
2. 解压MongoDB在D:\server\mongodb, 在D:\server\mongodb下创建d
Javascript魔法方法:__defineGetter__,__defineSetter__
hongtoushizi
js
转载自: http://www.blackglory.me/javascript-magic-method-definegetter-definesetter/
在javascript的类中,可以用defineGetter和defineSetter_控制成员变量的Get和Set行为
例如,在一个图书类中,我们自动为Book加上书名符号:
function Book(name){
错误的日期格式可能导致走nginx proxy cache时不能进行304响应
jinnianshilongnian
cache
昨天在整合某些系统的nginx配置时,出现了当使用nginx cache时无法返回304响应的情况,出问题的响应头: Content-Type:text/html; charset=gb2312 Date:Mon, 05 Jan 2015 01:58:05 GMT Expires:Mon , 05 Jan 15 02:03:00 GMT Last-Modified:Mon, 05
数据源架构模式之行数据入口
home198979
PHP 架构 行数据入口
注:看不懂的请勿踩,此文章非针对java,java爱好者可直接略过。
一、概念
行数据入口(Row Data Gateway):充当数据源中单条记录入口的对象,每行一个实例。
二、简单实现行数据入口
为了方便理解,还是先简单实现:
<?php
/**
* 行数据入口类
*/
class OrderGateway {
/*定义元数
Linux各个目录的作用及内容
pda158
linux 脚本
1)根目录“/” 根目录位于目录结构的最顶层,用斜线(/)表示,类似于
Windows
操作系统的“C:\“,包含Fedora操作系统中所有的目录和文件。 2)/bin /bin 目录又称为二进制目录,包含了那些供系统管理员和普通用户使用的重要
linux命令的二进制映像。该目录存放的内容包括各种可执行文件,还有某些可执行文件的符号连接。常用的命令有:cp、d
ubuntu12.04上编译openjdk7
ol_beta
HotSpot jvm jdk OpenJDK
获取源码
从openjdk代码仓库获取(比较慢)
安装mercurial Mercurial是一个版本管理工具。 sudo apt-get install mercurial
将以下内容添加到$HOME/.hgrc文件中,如果没有则自己创建一个: [extensions] forest=/home/lichengwu/hgforest-crew/forest.py fe
将数据库字段转换成设计文档所需的字段
vipbooks
设计模式 工作 正则表达式
哈哈,出差这么久终于回来了,回家的感觉真好!
PowerDesigner的物理数据库一出来,设计文档中要改的字段就多得不计其数,如果要把PowerDesigner中的字段一个个Copy到设计文档中,那将会是一件非常痛苦的事情。