11-MyBatis01
今日知识
1. MyBatis简介
2. MyBatis入门
3. 全局配置文件其他配置
4. MyBatis的映射文件
5. 动态SQL
6. mybatis和hibernate区别
MyBatis简介
1. MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
2. MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开
发者只需要关注 SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、
创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
3. 原理
1. Mybatis通过xml或注解的方式将要执行的各种statement(statement、prepared
Statemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进
行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
MyBatis入门
1. 导入依赖包和核心包
* <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
2. 添加log4j.properties文件到resources,用于打印日志信息
* # Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3. 创建pojo类User对象,创建数据库和表
4. 创建SqlMapConfig.xml,用于连接数据库的参数配置
* <?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">
<configuration>
<!-- 配置mybatis的环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用dbcp连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisday01?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--告诉mybatis加载映射文件-->
<mappers>
<mapper resource="User.xml"/>
</mappers>
</configuration>
5. 创建映射文件User.xml在resources文件中
* <?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">
<!--
namespace:命名空间,它的作用就是对SQL进行分类化管理,可以理解为SQL隔离
注意:使用mapper代理开发时,namespace有特殊且重要的作用
-->
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="com.rqy.model.User">
SELECT * FROM USER WHERE id=#{id}
</select>
<select id="findUserByName" parameterType="String" resultType="com.rqy.model.User">
SELECT * FROM USER WHERE username=#{username}
</select>
</mapper>
6. SqlMapConfig.xml配置文件加载映射文件
* <!--告诉mybatis加载映射文件-->
<mappers>
<mapper resource="User.xml"/>
</mappers>
7. 测试类
* public class MyTest {
@Test
public void test() throws IOException {
//a) 读取配置文件;
InputStream is= Resources.getResourceAsStream("sqlMapConfig.xml");
//b) 通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
//c) 通过SqlSessionFactory创建SqlSession。
SqlSession sqlSession = ssf.openSession();
//d) 调用SqlSession的操作数据库方法。
User user = sqlSession.selectOne("findUserByName", "张三");
System.out.println(user);
//e) 关闭SqlSession。
sqlSession.close();
}
}
更多案例讲解
1. 模糊查询用户信息
* <!--
[${}]:表示拼接SQL字符串
[${value}]:表示要拼接的是简单类型参数。
注意:
1、如果参数为简单类型时,${}里面的参数名称必须为value
2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname}
-->
<select id="findUserByName" parameterType="String" resultType="com.rqy.domain.User">
SELECT * FROM USER WHERE username like '%${value}%'
</select>
2. 插入用户信息
* <insert id="insertUser" parameterType="user">
INSERT into USER (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
</insert>
* @Test
public void test1() {
//d) 调用SqlSession的操作数据库方法。
User user=new User("任清阳","1",new Date(),"神州");
int insertUser = sqlSession.insert("insertUser", user);
sqlSession.commit();//默认事务不会给我提交
System.out.println("返回结果:"+insertUser);
}
3. 删除用户
* <delete id="deleteUser" parameterType="int">
DELETE FROM USER WHERE id=#{id}
</delete>
4. 修改用户
* <update id="updateUser" parameterType="user">
UPDATE USER SET username=#{username},sex=#{sex},WHERE id=#{id}
</update>
* @Test
public void test2() {
//d) 调用SqlSession的操作数据库方法。
User user=new User();
user.setId(34);
user.setUsername("任意");
user.setSex("2");
int result = sqlSession.insert("updateUser", user);
sqlSession.commit();//默认事务不会给我提交
System.out.println("返回结果:"+result);
}
5. 主键返回之MySQL自增主键
* <!--
[selectKey标签]:通过select查询来生成主键
[keyProperty]:指定存放生成主键的属性
[resultType]:生成主键所对应的Java类型
[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句
[last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
* <selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
* @Test
public void test3() {
//d) 调用SqlSession的操作数据库方法。
User user=new User("任清阳","1",new Date(),"神州");
int insertUser = sqlSession.insert("insertUser2", user);
sqlSession.commit();//默认事务不会给我提交
System.out.println("返回结果:"+insertUser);
System.out.println("id:"+user.getId());
}
6. 主键返回之MySQL自增UUID
* <selectKey keyProperty="id" resultType="String" order="BEFORE">
SELECT UUID()
</selectKey>
7. 小结
1. parameterType和resultType
parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。
resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。
2. #{}和${}
#{}:相当于预处理中的占位符?。
#{}里面的参数表示接收java输入参数的名称。
#{}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,#{}里面可以是value,也可以是其他。
#{}可以防止SQL注入。
${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。
${}会引起SQL注入,所以要谨慎使用。
${}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,${}里面只能是value。
3. selectOne和selectList
selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
selectList:可以查询0或N条记录
MyBatis的Dao编写
1. mapper代理方式实现
Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。
Mybatis会自动的为mapper接口生成动态代理实现类。
2. 实现mapper代理开发模式需要遵循一些开发规范
1. mapper接口的全限定名要和mapper映射文件的namespace的值相同。
2. mapper接口的方法名称要和mapper映射文件中的statement的id相同;
3. mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
4. mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;
通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:
* 模板代码已经去掉;
* 剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。
3.编写步骤
1. 重新写个UserMapper配置文件和定义mapper映射文件UserMapper.xml(内容同Users.xml,除了namespace的值),放到新创建的目录mapper下。
1. UserMapper接口创建
public interface UserMapper {
public int insertUser(User user);
public User findUserById(int id);
}
2. UserMapper.xml创建
<?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="com.rqy.mapper.UserMapper">
<insert id="insertUser" parameterType="user">
INSERT into USER (username,birthday,sex,address) VALUE (#{username},#{birthday},#{sex},#{address})
</insert>
<select id="findUserById" parameterType="int" resultType="com.rqy.model.User">
SELECT * FROM USER WHERE id=#{id}
</select>
</mapper>
2. 第二步:【添加映射配置文件】
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
3. 测试
public class MyTest3 {
SqlSession sqlSession=null;
@Before
public void before() throws IOException {
//a) 读取配置文件;
InputStream is= Resources.getResourceAsStream("sqlMapConfig.xml");
//b) 通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
//c) 通过SqlSessionFactory创建SqlSession。
sqlSession = ssf.openSession();
}
@After
public void after(){
//e) 关闭SqlSession。
sqlSession.close();
}
@Test
public void test1() {
//1. 通过session获取UserMapper的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//2. 创建一个用户
User user=new User("任清阳","1",new Date(),"神州");
//3. 保存用户
int insertUser =userMapper.insertUser(user);
System.out.println("返回结果:"+insertUser);
//4.查询用户信息
User userById = userMapper.findUserById(34);
System.out.println("userById:"+userById);
sqlSession.commit();//默认事务不会给我提交
}
}
全局配置文件其他配置
1. properties数据库文件配置
* 在resources配置个db.properties文件
* driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatisday01?useUnicode=true&characterEncoding
username==root
password=123456
* SqlMapConfig.xml中配置<properties resource="db.properties"/>
* <property name="driver" value="${driverClass}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
2. setting[了解]
3. typeAliases
* 别名是使用是为了在映射文件中,更方便的去指定参数和结果集的类型,不再用写很长的一段全限定名。
* 实例:在sqlMappingConfig.xml的<configuration>标签中写
<!--别名配置-->
<typeAliases>
<!--单个定义别名-->
<typeAlias type="com.rqy.model.User" alias="user"/>
<!--批量配置别名
[name],指定批量定义别名的类包,别名为类名(首字母大小写都可以)
-->
<package name="com.rqy.model"/>
</typeAliases>
* 在User.xml中可以设置parameterType为user, 书写简单
4. mappers:诉mybatis加载映射文件,几种方法
1. 方式一:<mapper resource="com/rqy/mapper/UserMapper.xml"/>
2. 方式二: <mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
3. 方式三:<mapper class="com.rqy.mapper.UserMapper"/>
* 与类名相同,一定要有映射文件相对应,此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
4. 方式四:<package name="com.rqy.mapper"/>
* 注册指定包下的所有映射文件
* 此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
5. 可使用注解开发,把xml文件删除(不推荐)
* 在对应的接口方法上加
@insert("sql语句")
@select("sql语句")
MyBatis的映射文件
1. 输入映射ParameterType
1. 传递简单类型:int
* SELECT * FROM USER WHERE id=#{?}
2. 传递POJO对象
* <insert id="insertUser" parameterType="user">
INSERT into USER (username,birthday,sex,address) VALUE (#{username},#{birthday},#{sex},#{address})
</insert>
3. 传递POJO包装对象
* <insert id="insertUser" parameterType="userMapper">
INSERT into USER (username,birthday,sex,address) VALUE (#{user.username},#{user.birthday},#{user.sex},#{user.address})
</insert>
* user指向的是UserMapper对象属性
* <!--别名配置-->
<typeAliases>
<!--单个定义别名-->
<typeAlias type="com.rqy.model.User" alias="user"/>
<!--批量配置别名
[name],指定批量定义别名的类包,别名为类名(首字母大小写都可以)
-->
<package name="com.rqy.model"/>
</typeAliases>
4. 传递Map对象
* public List<User> findUserListByMap(Map<String,Object> map);
* <select id="findUserListByMap" parameterType="hashmap" resultType="user">
SELECT * FROM USER WHERE username LIKE '%${username}%'
</select>
2. 输出映射 resultType/resultMap
1. resultType
* 使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
* 如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象;
* 如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象。
1. 输出简单类型
* 当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型,
2. 输出PoJo单个对象和pojo列表时,resultType的类型是一样,mapper接口方法的返回值不同
2. resultMap
1. 如果查询出来的列名和属性名不一致时,通过定义一个resultMap
将列名和pojo属性名之间作一个映射关系。
* 定义resultMap
* 使用resultMap作为statement的输出映射类型
* UserMapper.java
步骤一://返回结果为ResultMap
public User findUserByResultMap(int id);
步骤二:
<!--返回结果为ResultMap-->
<resultMap id="userResultMap" type="user">
<id column="id_" property="id"/>
<result column="username_" property="username"/>
<result column="sex_" property="sex"/>
</resultMap>
<select id="findUserByResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_,sex sex_ FROM USER WHERE id = #{?}
</select>
测试:System.out.println(userMapper.findUserByResultMap(1));
动态SQL
1. if和where
1. if标签:用作判断入参来使用,如果符合条件,则把if标签体内的sql拼接上,
* 注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’;
* 大于号用:>
* 小于号用:<
* 字符串使用单引号:''
*
2. Where标签:会去掉条件中的第一个and符号。
3. 测试:
SELECT * FROM USER
<where>
<if test="user!=null">
<if test="user.username !=null and user.username !=''">
username LIKE '%${user.username}%'
</if>
<if test="user.sex != null and user.sex !=''">
and sex=#{user.sex}
</if>
</if>
</where>
2. SQL片段
1. Mybatis提供了SQL片段的功能,可以提高SQL的可重用性。
2. 测试
3. <!--SQL片段-->
<sql id="select_user_where">
<if test="user!=null">
<if test="user.username !=null and user.username !=''">
username LIKE '%${user.username}%'
</if>
<if test="user.sex != null and user.sex !=''">
and sex=#{user.sex}
</if>
</if>
</sql>
<select id="findUserList" parameterType="userQuery" resultType="user">
SELECT * FROM USER
<where>
/*引用sql片段*/
<include refid="select_user_where"/>
</where>
</select>
3. foreach遍历
1. 查询指定id的用户(32,33,34)list类型
2. <select id="findUserByIds" parameterType="userQuery" resultType="user">
SELECT * FROM USER
<where>
<if test="ids!=null and ids.size > 0">
<!--foreach标签
collection:集合参数的名称,如果直接传入集合参数,则该处的参数只能写【list】
item:每次遍历出来的对象
open:开始遍历时拼接的串
close:结束遍历时拼接的串
separator:每次遍历对象之间要加的分割符
-->
<foreach collection="ids" item="id" open="and id in (" close=")" separator=",">
${id}
</foreach>
</if>
</where>
</select>
3. List无注解
int insertUsers(List<User> users)
<insert id="insertUsers">
intsert into user (username,password,age,emali) values
<foreach collection="list" item="user" separator=",">
(${user.username},#{user.password},#{user.age},#{user.email})
</foreach>
</insert>
4. List无注解,collection填的有变化
int insertUsers(@Param("users")List<User> users)
<insert id="insertUsers">
intsert into user (username,password,age,emali) values
<foreach collection="users" item="user" separator=",">
(${user.username},#{user.password},#{user.age},#{user.email})
</foreach>
</insert>
5. 当无注解时,数组和List在collection属性分别填array和list;
当包含@Param注解时collection中填@Param注解中的内容
mybatis和hibernate区别(面试题)
1. MyBatis技术特点:
* 好处
1. 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2. 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3. 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
* 缺点
1. 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
* Mysql:limit
* Oracle:rownum
2. 需要编写结果映射。
2. Hibernate技术特点:
* 好处:
1. 标准的orm框架,程序员不需要编写SQL语句。
2. 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
a) 以后,mysql数据迁移到oracle,只需要改方言配置
* 缺点:
1. 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
2. 程序员不能自主的去进行SQL性能优化。
3. 应用场景
1. MyBatis应用场景
* 需求多变的互联网项目,例如电商项目。
2. Hibaenate应用场景
* 需求明确、业务固定的项目,例如OA项目、ERP项目等。
今日知识
1. 关联查询
2. 延时加载
3. 查询缓存
关联查询
1.一对一 resultType实现
1. 写个定单的扩展类
public class OrdersExt extends Orders {
private String username;
private String address;
2. 声明定单接口
public interface OrdersMapper {
//根据订单id查询订单信息
public OrdersExt findOrdersUser(int id);
}
3. 声明定单配置文件
<mapper namespace="com.rqy.mapper.OrdersMapper">
<sql id="select_orders">
orders.id,
orders.number,
orders.createtime,
orders.note,
</sql>
<sql id="select_user">
user.username,
user.address
</sql>
<select id="findOrdersUser" parameterType="int" resultType="ordersExt">
SELECT
<include refid="select_orders"/>
<include refid="select_user"/>
FROM
orders,user
WHERE
orders.user_id=user.id and orders.id=#{?};
</select>
</mapper>
4. 加载映射文件
<mappers>
<package name="com.rqy.mapper"/>
</mappers>
5. 测试
@Test
public void test(){
OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
OrdersExt ordersExt = ordersMapper.findOrdersUser(3);
System.out.println(ordersExt);
sqlSession.commit();
}
6. 一对一 resultMap实现
<!--一对一 resultMap实现-->
<resultMap id="ordersRsMap" type="orders">
<id column="id" property="id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!--关联内部对象,Orders类有User user-->
<association property="user" javaType="com.rqy.model.User">
<id property="id" column="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findOrdersByRsMap" parameterType="int" resultMap="ordersRsMap">
SELECT
<include refid="select_orders"/>
<include refid="select_user"/>
FROM
orders,user
WHERE
orders.user_id=user.id and orders.id=#{?};
</select>
2.一对多 resultType实现
3.多对多 resultType实现
延时加载
- 概念:延迟加载又叫懒加载,也叫按需加载。也就是说先加载主信息,在需要的时候,再去加载从信息。
- 在mybatis中,resultMap标签的association标签和collection标签具有延迟加载的功能。
- 案例
11-MyBatis01的更多相关文章
- 地区sql
/*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...
- WinForm 天猫2013双11自动抢红包【源码下载】
1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...
- C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)
#include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...
- CSS垂直居中的11种实现方式
今天是邓呆呆球衣退役的日子,在这个颇具纪念意义的日子里我写下自己的第一篇博客,还望前辈们多多提携,多多指教! 接下来,就进入正文,来说说关于垂直居中的事.(以下这11种垂直居中的实现方式均为笔者在日常 ...
- C++ 11 多线程--线程管理
说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...
- CSharpGL(11)用C#直接编写GLSL程序
CSharpGL(11)用C#直接编写GLSL程序 +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharp ...
- ABP(现代ASP.NET样板开发框架)系列之11、ABP领域层——仓储(Repositories)
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之11.ABP领域层——仓储(Repositories) ABP是“ASP.NET Boilerplate Proj ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- C++11网络编程
Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(11)-系统日志和异常的处理①
系列目录 系统需要越来越自动化,我们需要引入日志记录和异常捕获管理员的操作记录需要被记录,看出哪些模块是频繁操作,分析哪些是不必要的功能,哪些是需要被优化的.系统的异常需要被捕获,而不是将系统出错显示 ...
随机推荐
- Java集合框架(java.util包)
集合的概念: 是一种工具类,可以存储任意数量.任意类型的对象(所以后面需要用到泛型,以约束集合中元素的类型) 集合的作用: 1.在类的内部对属性进行组织 2.方便快速定位属性位置 3.某些集合接口,提 ...
- python——pickle模块的详解
pickle模块详解 该pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议. “Pickling”是将Python对象层次结构转换为字节流的过程, “unpickling”是反 ...
- 从源码角度了解SpringMVC的执行流程
目录 从源码角度了解SpringMVC的执行流程 SpringMVC介绍 源码分析思路 源码解读 几个关键接口和类 前端控制器 DispatcherServlet 结语 从源码角度了解SpringMV ...
- .net 解析嵌套JSON
JSON格式文件如下:我们是要取出msgJsoncontent里面GeneralReportInfo下serviceData中的totalUseValue数据 { ", "mess ...
- 字典树(增删改查 HDU 5687)
度熊手上有一本神奇的字典,你可以在它里面做如下三个操作: 1.insert : 往神奇字典中插入一个单词 2.delete: 在神奇字典中删除所有前缀等于给定字符串的单词 3.search: 查询是否 ...
- kafka 中 zookeeper 具体是做什么的?
zookeeper 是 kafka 不可分割的一部分,可见其重要程度,所以我们有必要了解一下 zookeeper 在 kafka 中的具体工作内容. 而且,这也是面试时经常问的. zookeeper ...
- OGG bi-directional replication for Oracle DB
Overview of an Active-Active Configuration Oracle GoldenGate supports an active-active bi-directiona ...
- Error connecting to the Service Control Manager: 拒绝访问 Mongodb问题-解决
原文地址:https://blog.csdn.net/carrot5032/article/details/74742888 发现在mongodb.log里出现 2017-07-07T17:01:5 ...
- JUC中的原子操作类及其原理
昨天简单的看了看Unsafe的使用,今天我们看看JUC中的原子类是怎么使用Unsafe的,以及分析一下其中的原理! 一.简单使用AtomicLong 还记的上一篇博客中我们使用了volatile关键字 ...
- postman的简单介绍及运用
postman下载地址 https://www.getpostman.com/downloads/ postman的工作原理:发送请求给服务器,服务器处理postman发送的数据然后返回给postma ...