1.前端
vertical-align属性值和作用
- 线类,如 baseline、top、middle、bottom;
- 文本类,如 text-top、text-bottom;
- 上标下标类,如 sub、super;
- 数值百分比类,如 10px、1em、5%;
作用:https://segmentfault.com/a/1190000015366749
2.后端
2.1 sql
-- SQL架构
-- 给定一个表 tree,id 是树节点的编号, p_id 是它父节点的 id 。
--
-- +----+------+
-- | id | p_id |
-- +----+------+
-- | 1 | null |
-- | 2 | 1 |
-- | 3 | 1 |
-- | 4 | 2 |
-- | 5 | 2 |
-- +----+------+
-- 树中每个节点属于以下三种类型之一:
--
-- 叶子:如果这个节点没有任何孩子节点。
-- 根:如果这个节点是整棵树的根,即没有父节点。
-- 内部节点:如果这个节点既不是叶子节点也不是根节点。
--
--
-- 写一个查询语句,输出所有节点的编号和节点的类型,并将结果按照节点编号排序。上面样例的结果为:
--
--
--
-- +----+------+
-- | id | Type |
-- +----+------+
-- | 1 | Root |
-- | 2 | Inner|
-- | 3 | Leaf |
-- | 4 | Leaf |
-- | 5 | Leaf |
-- +----+------+
--
--
-- 解释
--
-- 节点 '1' 是根节点,因为它的父节点是 NULL ,同时它有孩子节点 '2' 和 '3' 。
-- 节点 '2' 是内部节点,因为它有父节点 '1' ,也有孩子节点 '4' 和 '5' 。
-- 节点 '3', '4' 和 '5' 都是叶子节点,因为它们都有父节点同时没有孩子节点。
-- 样例中树的形态如下:
结果
-- 需要有一个中间表 id,pid,sid的结构
select a.id as id,a.p_id as pid,min(b.id) as sid from tree a left join tree b on a.id = b.pid group by a.id
-- 通过判断id对应的pid和sid的个数判断是什么节点类型
select id, if(pid is null, "Root", if(sid is null, "Leaf", "Inner")) as Type
from (select a.id as id,a.p_id as pid,min(b.id) as sid from tree a left join tree b on a.id = b.p_id group by a.id) temp
2.2 python中的函数
在Python中,定义一个函数要使用def
语句,依次写出函数名、括号、括号中的参数和冒号:
,然后,在缩进块中编写函数体,函数的返回值用return
语句返回。
def add(a,b):
return a+b;
# 空函数,用来占位
def nop():
pass
if __name__ == "__main__":
print(add(3,4))
2.3 框架
mybatis中的getMapper做了什么
// DefaultSqlSession#getMapper
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
如果方法返回值是一个泛型的话可以在方法前加个<t>方法</t>
// protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
// MapperRegistry#getMapper
// 用于注册Mapper接口Class对象,和MapperProxyFactory对象对应关系
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
这里的mapperProxyFactory.newInstance不是一个静态类,所以是哪里有初始化这个factory,这个是存储在knownMappers中的一个映射关系,所以MapperRegistry中一定会有注册的方法。这里的factory中为什么是需要一个初始化后的类呢?可以看到factory中的属性,这里的每个type(Class)创建了一个factory,factory中存储了Method和MapperMethod的映射,如果是静态方法的话,不同生成变量之间的公共属性就没法共用了。这里把后面生成的MapperProxy中共用的方法放在了factory中,这样同一个个类型中就可以复用这些方法了。
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
// 根据Mapper接口Class对象,创建MapperProxyFactory对象,并注册到knownMappers属性中
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
knownMappers.put(type, new MapperProxyFactory<T>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
网友评论