学习mybatis-3 step by step 篇二
Mapper XML 文件
基本的*Mapper.xml文件配置就不熬述了具体可参考:
http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
1、sql元素
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
这个 SQL 片段可以被包含在其他语句中,例如:
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
属性值可以用于包含的refid属性或者包含的字句里面的属性值,例如:
<sql id="sometable">
${prefix}Table
</sql> <sql id="someinclude">
from
<include refid="${include_target}"/>
</sql> <select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>
上面这段SQL首先引用了someinclude然后再someinclude里面又引用了sometable。利用该功能配合if就能动态生成SQL语句了。
2、使用Mybatis优雅的解决N+1查询问题(关联的嵌套查询)
概括地讲,N+1 查询问题可以是这样引起的:
- 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
- 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。
以上问题可以使用关联嵌套查询来解决问题,以下介绍一下嵌套查询的标签<association>属性的作用。
- column:来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字符串是相同的。 column 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
- select:另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面 有一个详细的示例。 select 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
- fetchType:可选的。有效值为 lazy和eager。 如果使用了,它将取代全局配置参数lazyLoadingEnabled。
先举一个简单的例子:客户表customer和car是有一对多的关系,假设有实体类如下:
package com.zealzhangz.entity; import java.io.Serializable;
import java.util.List; public class Customer implements Serializable { private static final long serialVersionUID = 7500918067281634276L; private String name; // 名称 private String sex; // 性别 private String idCar; private Car customerCar; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getIdCar() {
return idCar;
} public void setIdCar(String idCar) {
this.idCar = idCar;
} public Car getCustomerCar() {
return customerCar;
} public void setCustomerCar(Car customerCar) {
this.customerCar = customerCar;
}
}
如果要获取客户和车辆的信息,一般的做法需要两次查询才能查出结果。当然可以换一种方式,把Car中字段拿到Customer中来,SQL JOIN查询也能查出结果,对于List<car>这种情况JOIN就无能为力了。但是mybatis已经提供了直接优雅
完成这种查询的功能SQL如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="CustomerMapper">
<resultMap type="Customer" id="customerMap">
<association property="customerCar" column="idCar" javaType="Car" select="selectCar"/>
</resultMap>
<select id="selectCustomer" resultMap="customerMap" parameterType="string">
select name,sex,cc.id_car AS idCar from customer c INNER JOIN customer_car cc ON c.pk_id=cc.id_customer where c.pk_id = CAST(#{pk_id} AS UNSIGNED)
</select> <select id="selectCar" resultType="Car">
select car_prefix AS carPrefix,car_no AS carNo,vin,car_brand_name AS carBrandName, car_series_mame AS carSeriesMame from car where pk_id = CAST(#{id} AS UNSIGNED)
</select>
</mapper>
结果如下:
{
"customerCar": {
"carBrandName": "Jeep",
"carNo": "A666666",
"carPrefix": "苏",
"carSeriesMame": "Compass [指南者]",
"vin": "1C4NJCCA9CD645865"
},
"name": "张先生",
"sex": "先生"
}
更复杂的情形有多辆车的情况,这种情况我们稍后考虑。
注意:以上联合查询是一个分离的复杂的联合查询,下面这个是一个非常简单的示例 来说明它如何工作。代替了执行一个分离的语句:
<select id="selectCustomerCar" resultType="Customer" parameterType="string">
SELECT
name,
sex,
cc.id_car AS idCar,
r.car_prefix AS carPrefix,
r.car_no AS carNo,
vin,
car_brand_name AS carBrandName,
car_series_mame AS carSeriesMame
FROM
tm_customer c
INNER JOIN
tm_customer_car cc ON c.pk_id = cc.id_customer
INNER JOIN
tm_car r ON cc.id_car = r.pk_id
WHERE
c.pk_id = CAST(#{pk_id} AS UNSIGNED)
</select>
下面使用两个resultMap来联合映射上面的查询结果:
<resultMap id="customerCarResult" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<association property="customerCar" column="idCar" javaType="Car" resultMap="carResult"/>
</resultMap> <resultMap id="carResult" type="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
</resultMap>
非常重要: id元素在嵌套结果映射中扮演着非 常重要的角色。你应该总是指定一个或多个可以唯一标识结果的属性。实际上如果你不指定它的话, MyBatis仍然可以工作,但是会有严重的性能问题。在可以唯一标识结果的情况下, 尽可能少的选择属性。主键是一个显而易见的选择(即使是复合主键)。
现在,上面的示例用了外部的结果映射元素来映射关联。这使得Car结果映射可以 重用。然而,如果你不需要重用它的话,或者你仅仅引用你所有的结果映射合到一个单独描 述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:
<resultMap id="customerCarResultUnion" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<association property="customerCar" javaType="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
</association>
</resultMap>
假设有一种业务,每个customer有一辆日常用车还有一辆备用车(这个业务现实中可能并不存在),客户实体就变成这个样子了:
import java.io.Serializable;
import java.util.List; public class Customer implements Serializable { private static final long serialVersionUID = 7500918067281634276L; private String idCustomer; private String name; // 名称 private String sex; // 性别 private String idCar; private Car customerCar; private Car backupCar; //备用车 public String getIdCustomer() {
return idCustomer;
} public void setIdCustomer(String idCustomer) {
this.idCustomer = idCustomer;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getIdCar() {
return idCar;
} public void setIdCar(String idCar) {
this.idCar = idCar;
} public Car getCustomerCar() {
return customerCar;
} public void setCustomerCar(Car customerCar) {
this.customerCar = customerCar;
} public Car getBackupCar() {
return backupCar;
} public void setBackupCar(Car backupCar) {
this.backupCar = backupCar;
}
}
两个Car类型的字段:customerCar、backupCar,这个时候SQL查询怎么区分呢?
因为结果中的列名与resultMap中的列名不同。 你需要指定columnPrefix去重用映射ba_car结果的resultMap。
<resultMap id="carResult" type="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
</resultMap> <resultMap id="customerCarResultAll" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<association property="customerCar" resultMap="carResult"/>
<association property="backupCar" resultMap="carResult" columnPrefix="ba_"/>
</resultMap> <select id="selectCustomerCarAll" resultMap="customerCarResultAll" parameterType="string">
SELECT
c.pk_id AS idCustomer,
c.name,
c.sex,
cc.id_car AS idCar,
r.car_prefix AS carPrefix,
r.car_no AS carNo,
r.vin,
r.car_brand_name AS carBrandName,
r.car_series_mame AS carSeriesMame,
'1314182348972' AS ba_idCar,
'云' AS ba_carPrefix,
'AR6248' AS ba_carNo,
'1231sdfhs623462e7' AS ba_vin,
'五羊' AS ba_carBrandName,
'本田' AS ba_carSeriesMame
FROM
tm_customer c
INNER JOIN
tm_customer_car cc ON c.pk_id = cc.id_customer
INNER JOIN
tm_car r ON cc.id_car = r.pk_id
WHERE
c.pk_id = CAST(#{pk_id} AS UNSIGNED)
</select>
结果如下:
{
"backupCar": {
"carBrandName": "五羊",
"carNo": "AR6248",
"carPrefix": "云",
"carSeriesMame": "本田",
"idCar": "1314182348972",
"vin": "1231sdfhs623462e7"
},
"customerCar": {
"carBrandName": "Jeep",
"carNo": "A666666",
"carPrefix": "苏",
"carSeriesMame": "Compass [指南者]",
"idCar": "10545406337939703159",
"vin": "1C4NJCCA9CD645865"
},
"idCustomer": "10545406337939703158",
"name": "张先生",
"sex": "先生"
}
集合的嵌套查询
假设这种场景,一个客户有很多辆车且车和车之间没有逻辑关系,这时候我们会用private List<Car> cars;来存储所有车辆的信息。这种情况改怎么写查询呢?
<resultMap id="customerCarListResult" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<collection property="cars" javaType="ArrayList" column="idCustomer" ofType="Car" select="selectCarByIdCustomer"/>
</resultMap> <select id="selectCarByIdCustomer" resultType="Car">
SELECT
r.car_prefix AS carPrefix,
r.car_no AS carNo,
r.vin,
r.car_brand_name AS carBrandName,
r.car_series_mame AS carSeriesMame
FROM
tm_customer_car cc INNER JOIN
tm_car r ON cc.id_car = r.pk_id
WHERE
cc.id_customer = CAST(#{idCustomer} AS UNSIGNED)
</select> <select id="selectCustomerListCar" resultMap="customerCarListResult" parameterType="string">
select pk_id AS idCustomer,name,sex from tm_customer where pk_id = CAST(#{pk_id} AS UNSIGNED)
</select>
结果如下图:
{
"cars": [
{
"carBrandName": "Jeep",
"carNo": "A666666",
"carPrefix": "苏",
"carSeriesMame": "Compass [指南者]",
"vin": "1C4NJCCA9CD645865"
},
{
"carBrandName": "宝马",
"carNo": "A86866",
"carPrefix": "苏",
"carSeriesMame": "X5 xDrive35i",
"vin": "5UXZV4C51D0B11025"
}
],
"idCustomer": "10545406337939703158",
"name": "张先生",
"sex": "先生"
}
这里我们应该注意很多东西,但大部分代码和上面的关联元素是非常相似的。首先,你应 该注意我们使用的是集合元素。然后要注意那个新的“ofType”属性。这个属性用来区分 JavaBean(或字段)属性类型和集合包含的类型来说是很重要的。所以你可以读出下面这个 映射:
<collection property="cars" javaType="ArrayList" column="idCustomer" ofType="Car" select="selectCarByIdCustomer"/>
读作: “在Car类型的 ArrayList 中的 cars 的集合。”
javaType 属性是不需要的,因为 MyBatis 在很多情况下会为你算出来。所以你可以缩短 写法:
<collection property="cars" column="idCustomer" ofType="Car" select="selectCarByIdCustomer"/>
集合的嵌套结果
至此,我们可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性,请看如下SQL:
<select id="selectCustomerListCarUnion" resultMap="selectCustomerListCarUnionResult">
SELECT
c.pk_id AS idCustomer,
c.name,
c.sex,
cc.id_car AS idCar,
r.car_prefix AS carPrefix,
r.car_no AS carNo,
r.vin,
r.car_brand_name AS carBrandName,
r.car_series_mame AS carSeriesMame
FROM
tm_customer c
INNER JOIN
tm_customer_car cc ON c.pk_id = cc.id_customer
LEFT JOIN
tm_car r ON r.pk_id = cc.id_car
WHERE
c.pk_id = CAST(#{idCustomer} AS UNSIGNED)
</select>
我们在一个SQL中查询出了一个客户的所有车辆信息,查询的结果形式如下:
客户1 车辆1
客户1 车辆2
我们又一次联合了客户和车辆表,结果列标签的简单映射。现 在用汽车映射集合映射客户,可以简单写为:
<resultMap id="selectCustomerListCarUnionResult" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<collection property="cars" ofType="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
</collection>
</resultMap>
注意这里的<collection property="cars" ofType="Car">和上面<association property="customerCar" javaType="Car">不同支出就是ofType是针对集合的。
同样,要记得 id 元素的重要性,如果你不记得了,请阅读上面的关联部分。
同样, 如果你引用更长的形式允许你的结果映射的更多重用, 你可以使用下面这个替代 的映射:
<resultMap id="selectCustomerListCarUnionCustomerResult" type="Customer">
<id property="idCustomer" column="idCustomer"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<collection property="cars" ofType="Car" resultMap="carListUnion" columnPrefix="car_"/>
</resultMap> <resultMap id="carListUnion" type="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
</resultMap> <select id="selectCustomerListCarUnion" resultMap="selectCustomerListCarUnionCustomerResult">
SELECT
c.pk_id AS idCustomer,
c.name,
c.sex,
cc.id_car AS car_idCar,
r.car_prefix AS car_carPrefix,
r.car_no AS car_carNo,
r.vin AS car_vin,
r.car_brand_name AS car_carBrandName,
r.car_series_mame AS car_carSeriesMame
FROM
tm_customer c
INNER JOIN
tm_customer_car cc ON c.pk_id = cc.id_customer
LEFT JOIN
tm_car r ON r.pk_id = cc.id_car
WHERE
c.pk_id = CAST(#{idCustomer} AS UNSIGNED)
</select>
鉴别器
有的时候结果集的映射需要根据结果集的每个字段进行动态映射,比如结果实体有继承关系时。 鉴别器非常容易理 解,因为它的表现很像 Java 语言中的 switch 语句。比如:
<select id="selectCarDiscriminator" resultMap="carResultDiscriminator">
SELECT
pk_id AS idCar,
car_prefix AS carPrefix,
car_no AS carNo,
vin AS vin,
car_brand_name AS carBrandName,
car_series_mame AS carSeriesMame,
2 AS flag
FROM
tm_car
WHERE
pk_id = CAST(#{pk_id} AS UNSIGNED)
</select> <resultMap id="carResultDiscriminator" type="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
<discriminator javaType="int" column="flag">
<case value="1" resultMap="test1Result"/>
<case value="2" resultMap="test2Result"/>
</discriminator>
</resultMap> <resultMap id="test1Result" type="Car">
<result property="test1" column="flag"/>
</resultMap>
<resultMap id="test2Result" type="Car">
<result property="test2" column="vin"/>
</resultMap>
以上逻辑<discriminator javaType="int" column="flag">中flag的值(1或2)动态映射test1Result或test2Result
以上result可简写为如下:
<resultMap id="carResultDiscriminator" type="Car">
<id property="idCar" column="idCar"/>
<result property="carPrefix" column="carPrefix"/>
<result property="carNo" column="carNo"/>
<result property="vin" column="vin"/>
<result property="carBrandName" column="carBrandName"/>
<result property="carSeriesMame" column="carSeriesMame"/>
<discriminator javaType="int" column="flag">
<case value="1" resultMap="test1Result">
<result property="test1" column="flag"/>
</case>
<case value="2" resultMap="test2Result">
<result property="test2" column="vin"/>
</case>
</discriminator>
</resultMap>
自动映射
当自动映射查询结果时,MyBatis会获取sql返回的列名并在java类中查找相同名字的属性(忽略大小写)。 这意味着如果Mybatis发现了ID列和id属性,Mybatis会将ID的值赋给id。通常数据库列使用大写单词命名,单词间用下划线分隔;而java属性一般遵循驼峰命名法。 为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase设置为true。
有三种自动映射等级:
- NONE - 禁用自动映射。仅设置手动映射属性。
- PARTIAL - 将自动映射结果除了那些有内部定义内嵌结果映射的(joins).
- FULL - 自动映射所有。
默认值是PARTIAL,这是有原因的。当使用FULL时,自动映射会在处理join结果时执行,并且join取得若干相同行的不同实体数据,因此这可能导致非预期的映射。比如两个实体都有id属性,SELECT出来的id就不知道映射给谁。
缓存
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
<cache/>
字面上看就是这样。这个简单语句的效果如下:
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
- 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。
可用的收回策略有:
- LRU – 最近最少使用的:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false
注意:如果手动修改了数据库的数据就可能会发生脏读,因为手动改数据触发不了mybatis的缓存更新机制。
使用自定义缓存
除了这些自定义缓存的方式, 你也可以通过实现你自己的缓存或为其他第三方缓存方案 创建适配器来完全覆盖缓存行为。
<cache type="com.domain.something.MyCustomCache"/>
这个示 例展 示了 如何 使用 一个 自定义 的缓 存实 现。type 属 性指 定的 类必 须实现 org.mybatis.cache.Cache 接口。这个接口是 MyBatis 框架中很多复杂的接口之一,但是简单 给定它做什么就行。
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
boolean hasKey(Object key);
Object removeObject(Object key);
void clear();
}
记得缓存配置和缓存实例是绑定在 SQL 映射文件的命名空间是很重要的。因此,所有 在相同命名空间的语句正如绑定的缓存一样。 语句可以修改和缓存交互的方式, 或在语句的 语句的基础上使用两种简单的属性来完全排除它们。默认情况下,语句可以这样来配置:
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>
因为那些是默认的,你明显不能明确地以这种方式来配置一条语句。相反,如果你想改 变默认的行为,只能设置 flushCache 和 useCache 属性。比如,在一些情况下你也许想排除 从缓存中查询特定语句结果,或者你也许想要一个查询语句来刷新缓存。相似地,你也许有 一些更新语句依靠执行而不需要刷新缓存。
参照缓存
这个特殊命名空间的唯一缓存会被使用或者刷新相同命名空间内 的语句。也许将来的某个时候,你会想在命名空间中共享相同的缓存配置和实例。在这样的 情况下你可以使用 cache-ref 元素来引用另外一个缓存。
<cache-ref namespace="com.someone.application.data.SomeMapper"/>
学习mybatis-3 step by step 篇二的更多相关文章
- Linux 学习 step by step (2)
Linux 学习 step by step (2) Linux,想要我说爱你真的不容易了,尽管,你是ubutun,尽管,你有蛮界面.但是,操作你,还是没有操作windows那么的如鱼得水了.为了更 ...
- MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九
<Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次 SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...
- C# step by step 学习笔记8 CHAPTER 9 使用枚举和结构创建值类型
C# 2012 step by step 学习笔记8 CHAPTER 9 使用枚举和结构创建值类型 本章内容 声明一个枚举类型 创建并使用一个枚举类型 声明一个结构类型 创建并使用一个结构类型 解释结 ...
- 源码学习系列之SpringBoot自动配置(篇二)
源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (二) 图片验证码的识别
上一篇文章讲了“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 一 京东 商品搜索 ...
- java学习笔记-JavaWeb篇二
JavaWEB篇二 45 HttpSession概述46 HttpSession的生命周期 47 HttpSession常用方法示例48 HttpSessionURL重写 49 HttpSession ...
- 【学习笔记】Baby Step Giant Step算法及其扩展
1. 引入 Baby Step Giant Step算法(简称BSGS),用于求解形如\(a^x\equiv b\pmod p\)(\(a,b,p\in \mathbb{N}\))的同余方程,即著名的 ...
- 精通initramfs构建step by step
(一)hello world 一.initramfs是什么 在2.6版本的linux内核中,都包含一个压缩过的cpio格式 的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs ...
- 稀疏表示step by step(转)
原文地址:稀疏表示step by step(转)作者:野火春风 稀疏表示step by step(1) 声明:本人属于绝对的新手,刚刚接触“稀疏表示”这个领域.之所以写下以下的若干个连载,是鼓 ...
- 数百个 HTML5 例子学习 HT 图形组件 – 3D建模篇
http://www.hightopo.com/demo/pipeline/index.html <数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇>里提到 HT 很 ...
随机推荐
- 用lua扩展你的Nginx(整理)
首先得声明.这不是我的原创,是在网上搜索到的一篇文章,原著是谁也搞不清楚了.按风格应该是属于章亦春的文章. 整理花了不少时间,所以就暂写成原创吧. 一. 概述 Nginx是一个高性能.支持高并发的,轻 ...
- Mantle 与Injection
本来Injection可以本地打补丁实时修改代码,但是不知道Mantle的数据类为何不能打补丁,可能因为Mantle利用了很多运行时的技术吧.
- php array_rand()函数从数组中随机选择一个或多个元素
php使用array_rand()函数从数组中随机选择一个或多个元素的方法. 使用array_rand() 函数从数组中随机选出一个或多个元素,并返回. array_rand(array,numbe ...
- Python常用函数及说明
原文地址:博客园 CSDN 基本定制型C.__init__(self[, arg1, ...]) 构造器(带一些可选的参数)C.__new__(self[, arg1, ...]) 构造器(带一些可 ...
- set的一些数学运算
python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和 ...
- Filter—过滤器和拦截器的区别
1.首先要明确什么是拦截器.什么是过滤器 1.1 什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加 ...
- django学习网站
http://www.ziqiangxuetang.com/django/django-qrcode.html
- sql性能优化(摘自网络)
索引,索引!!!为经常查询的字段建索引!! 但也不能过多地建索引.insert和delete等改变表记录的操作会导致索引重排,增加数据库负担. 优化目标 1.减少 IO 次数 IO永远是数据库最容易瓶 ...
- IntelliJ IDEA 编译Java程序出现 'Error:java: 无效的源发行版: 9' 解决方法
最新安装的IntelliJ IDEA 2018.1编译器,创建Java Project,并选择之前安装好的Eclipse配置的JDK,如图所示: 在工程中添加 Main.class, main函数中写 ...
- iOS开发之AFNetworking实现数据传输和文件上传
//传输数据 1 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.r ...