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:可选的。有效值为 lazyeager。 如果使用了,它将取代全局配置参数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 篇二的更多相关文章

  1. Linux 学习 step by step (2)

      Linux 学习 step by step (2) Linux,想要我说爱你真的不容易了,尽管,你是ubutun,尽管,你有蛮界面.但是,操作你,还是没有操作windows那么的如鱼得水了.为了更 ...

  2. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  3. C# step by step 学习笔记8 CHAPTER 9 使用枚举和结构创建值类型

    C# 2012 step by step 学习笔记8 CHAPTER 9 使用枚举和结构创建值类型 本章内容 声明一个枚举类型 创建并使用一个枚举类型 声明一个结构类型 创建并使用一个结构类型 解释结 ...

  4. 源码学习系列之SpringBoot自动配置(篇二)

    源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...

  5. e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (二) 图片验证码的识别

    上一篇文章讲了“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 一 京东 商品搜索 ...

  6. java学习笔记-JavaWeb篇二

    JavaWEB篇二 45 HttpSession概述46 HttpSession的生命周期 47 HttpSession常用方法示例48 HttpSessionURL重写 49 HttpSession ...

  7. 【学习笔记】Baby Step Giant Step算法及其扩展

    1. 引入 Baby Step Giant Step算法(简称BSGS),用于求解形如\(a^x\equiv b\pmod p\)(\(a,b,p\in \mathbb{N}\))的同余方程,即著名的 ...

  8. 精通initramfs构建step by step

    (一)hello world  一.initramfs是什么  在2.6版本的linux内核中,都包含一个压缩过的cpio格式 的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs ...

  9. 稀疏表示step by step(转)

    原文地址:稀疏表示step by step(转)作者:野火春风 稀疏表示step by step(1)     声明:本人属于绝对的新手,刚刚接触“稀疏表示”这个领域.之所以写下以下的若干个连载,是鼓 ...

  10. 数百个 HTML5 例子学习 HT 图形组件 – 3D建模篇

    http://www.hightopo.com/demo/pipeline/index.html <数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇>里提到 HT 很 ...

随机推荐

  1. 用lua扩展你的Nginx(整理)

    首先得声明.这不是我的原创,是在网上搜索到的一篇文章,原著是谁也搞不清楚了.按风格应该是属于章亦春的文章. 整理花了不少时间,所以就暂写成原创吧. 一. 概述 Nginx是一个高性能.支持高并发的,轻 ...

  2. Mantle 与Injection

    本来Injection可以本地打补丁实时修改代码,但是不知道Mantle的数据类为何不能打补丁,可能因为Mantle利用了很多运行时的技术吧.

  3. php array_rand()函数从数组中随机选择一个或多个元素

    php使用array_rand()函数从数组中随机选择一个或多个元素的方法. 使用array_rand() 函数从数组中随机选出一个或多个元素,并返回.  array_rand(array,numbe ...

  4. Python常用函数及说明

    原文地址:博客园  CSDN 基本定制型C.__init__(self[, arg1, ...]) 构造器(带一些可选的参数)C.__new__(self[, arg1, ...]) 构造器(带一些可 ...

  5. set的一些数学运算

    python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和 ...

  6. Filter—过滤器和拦截器的区别

    1.首先要明确什么是拦截器.什么是过滤器 1.1 什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加 ...

  7. django学习网站

    http://www.ziqiangxuetang.com/django/django-qrcode.html

  8. sql性能优化(摘自网络)

    索引,索引!!!为经常查询的字段建索引!! 但也不能过多地建索引.insert和delete等改变表记录的操作会导致索引重排,增加数据库负担. 优化目标 1.减少 IO 次数 IO永远是数据库最容易瓶 ...

  9. IntelliJ IDEA 编译Java程序出现 'Error:java: 无效的源发行版: 9' 解决方法

    最新安装的IntelliJ IDEA 2018.1编译器,创建Java Project,并选择之前安装好的Eclipse配置的JDK,如图所示: 在工程中添加 Main.class, main函数中写 ...

  10. iOS开发之AFNetworking实现数据传输和文件上传

    //传输数据 1 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.r ...