mybatis技术总结
一、框架概述
day1
1.什么是框架
框架是系统的可重用设计,是对J2EE底层技术的封装(JDBC,IO流,多线程,Servlet,Socket)。
2.框架解决了哪些问题?
1.解决了技术整合问题
在JavaEE体系中,有着各式各样的技术,不同的软件企业,根据自身的业务需求选择不同的技术,容易造成应用依赖技术,增加了项目开发 的复杂性和技术风险性。企业项目中应该将应用的设计与实现技术解耦。
2.解决提升开发效率的问题
企业项目中使用框架,程序员不再需要重复造轮子,只需要专注实现业务需求,使用框架的方便性,提高开发效率
3.解决了稳定性的问题
一个成熟的框架,经过了众多企业项目的验证使用,稳定性有保证
3.J2EE项目的分层:
web层(表现层)-业务层(service)-持久层(dao)
二、总结jdbc开发的问题
1.jdbc开发步骤:
加载驱动
创建数据库连接对象
定义sql语句
创建Statement语句对象
设置参数
执行
处理结果集
释放资源
2.jdbc案例程序
第一步:创建项目
第二步:配置pom.xml,导入数据库驱动包
第三步:编写案例代码
public class JdbcTest01 { public static void main(String[] args) {
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
//1.创建jdbc驱动
try {
Class.forName("com.mysql.jdbc.Driver");
//2.新建连接
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mybatistest", "root", "root");
// //3.书写sql
String sql="SELECT * FROM USER WHERE id =?";
//4.创建预处理对象
statement = connection.prepareStatement(sql);
//5.获得结果集对象,设置参数
statement.setInt(1,1);
//6.执行查询
resultSet = statement.executeQuery(); while (resultSet.next()){
System.out.println("用户的id为:"+resultSet.getInt("id")+"用户名:"+resultSet.getString("username")); }
} catch (Exception e) {
e.printStackTrace();
}finally {
//7.关闭对象
try { if (resultSet!=null) resultSet.close(); if (statement!=null) statement.close();
if (connection!=null) connection.close();
}catch (Exception e){
e.printStackTrace();
}
} }
}
3.总结jdbc开发的问题
1.频繁创建数据库连接对象和释放,容易造成系统资源的浪费,从而影响系统的性能,在企业中,可以通过使用连接池技术解决这个问题,但是使用jdbc需要我们自己来实现连接池,mybatis内部提供连接池
2.sql语句的定义,参数设计,结果集处理存在硬编码,在企业中sql语句因为需求的变化,所以变化频繁,一但发生变化,需要修改java代码,系统需要重新编译,重新发布,不好维护
3.结果集处理存在重复代码,每次都要遍历resultset结果集,获取一行数据,封装为对象处理麻烦,如果可以自动把行数据封装为java对象这样就方便多了
三、mybatis框架快速入门
1.入门程序实现步骤分析:
第一步:创建Maven项目
第二步:配置pom.xml,导入依赖包
mysql驱动包
mybatis框架包
log4j日志包
第三步:编写主配置文件(sqlMapConfig.xml)
第四步:编写用户实体类
第五步:编写用户dao接口
第六步:编写用户dao接口的映射文件(建立java对象与sql语句的对应关系)
第七步:在主配置文件sqlMapConfig.xml中,加载接口配置文件
第八步:编写测试代码
public class MybatisDemo { public static void main(String[] args) { SqlSession session=null;
InputStream inputStream =null;
try {
//1.加载读取主配置文件
inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.构建新建sqlsessionfatory的必要条件
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//根据配置文件创建sqlsessionfatory
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
//3.根据sqlsessionfactory创建session
session = sqlSessionFactory.openSession(); //4.根据session创建dao代理对象
UserDao userDao = session.getMapper(UserDao.class);
// System.out.println(userDao.getClass()); //5.通过dao代理对象执行sql操作数据库数据
List<User> userList = userDao.selectAllUser();
for (User user:userList){
System.out.println(user);
} } catch (IOException e) {
e.printStackTrace();
}finally {
try {
//6.释放资源
session.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
四、mybatis框架介绍
mybatis是Apache软件基金会下的一个开源项目,前身是Ibatis框架。2010年这个项目由apache 软件基金会迁移到google code下,改名为mybatis。2013年11月又迁移到了github(https://github.com/mybatis/mybatis-3/releases)。
mybatis是一个持久层的框架,是对jdbc操作数据库的封装,使开发者只需要关注业务本身,不需要花费精力去处理加载驱动、创建数据库连接对象、创建statement语句对象、参数设置、结果集处理等一系列繁杂的过程代码。
mybatis框架通过xml或注解进行配置,将java对象与sql语句中的参数自动映射生成最终执行的sql语句,并将sql语句执行结果自动映射成java对象。
三句话概括介绍:
1. mybatis框架早期版本叫做Ibatis,目前源代码托管在github
2. mybatis框架是对jdbc操作数据库的封装,是一个持久层的框架
3. mybatis框架通过xml或者注解进行配置,实现java对象与sql语句的自动对应关系(orm映射)
五、自定义mybatis框架
1.解析配置文件
1.1.编写Mapper类:namespace名称空间,id属性值,resultType返回值,执行的sql语句
1.2.编写Configuraton类型:连接数据库的四个基本要素,数据源对象(c3p0),接口映射文件
线程安全:
SqlSessionFactory:线程安全,因为它是只读的
SqlSession:线程不安全
两个用户:
用户一:SqlSession新增用户记录,操作时间很久。。。。。
用户二:SqlSession新增订单记录,很快就执行完,并且提交事务。
day2
一、mybatis框架实现CRUD操作
1.搭建mybatis框架环境:
第一步:创建maven项目
第二步:配置pom.xml,导入依赖包
mybatis框架包
mysql数据库驱动包
junit测试包
log4j日志包
第三步:编写配置文件(sqlMapConfig.xml)
sqlMapConfig.xml
dao接口映射文件
log4j.properties
加载dao接口映射文件
2.实现根据用户id查询用户:
第一步:编写用户实体类
第二步:编写用户dao(mapper)接口
第三步:编写用户dao(mapper)接口映射文件
第四步:在sqlMapConfig.xml,加载dao接口映射文件
根据用户Id查询用户,说明:
3.实现根据用户名称模糊查询用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试
4.新增用户:
4.1.事务(增删改):事务的四个基本特性(ACID)
原子性,一致性,隔离性,持久性
4.2.事务提交方式:
手动提交
自动提交
4.3.注册成为一个网站的用户
用户id是自动增长,不需要传递
网站要给我分配权限,需要使用用户id
要不要查询出这个id值?答案是要
4.4如何获取数据库维护的主键值?
5.根据用户id修改用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试
6.根据用户id删除用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试
二、mybatis框架输入输出映射
1.ParameterType输入映射(参数)
java简单类型
pojo类型
pojo包装类型:就是在pojo中包含了其它的pojo,通常用于接收综合查询条件
第一步:编写pojo包装类型实体类
第二步:声明mapper接口方法
第三步:配置mapper映射文件
第四步:测试
2.ResultType返回值输出
3.ResultMap返回值输出
需求:查询全部订单表数据
需求实现:
编写订单实体类
编写订单mapper接口
编写订单mapper映射文件
在sqlMapConfig.xml加载订单mapper映射文件
三、mybatis框架持久层开发的两种方法
1.mapper代理开发方法【重点掌握-记住开发的原则】
2.传统的dao开发方法【了解】
第一步:编写mapper映射文件
第二步:编写dao接口
第三步:编写dao接口实现类
第四步:测试
四、mybatis框架注意事项
1.占位符#{}与字符串拼接符${}区别【重点】
(1).占位符 #{}
当参数传递的是java简单类型(八种基本类型+字符串String)的时候,花括号中的内容可以是任意字符串
(2).字符串拼接符${}
当参数传递的是java简单类型(八种基本类型+字符串String)的时候,花括号中的内容只能是value
(3).#{}、${}当参数传递的pojo类型的时候,花括号中的内容都是pojo的属性
2.
id:唯一标识名称,与接口方法名称一致
parameterType:输入参数类型,与接口方法形参类型一致
resultType:
返回值类型(暂时注意:它是po类的全限定名称),与接口方法返回值类型一致,如果是List<User>,这种返回形式,则直接返回User
#{id}:占位符,相当于jdbc中的问号
获取数据库维护的主键值
selectKey:
作用:查询数据库维护的主键值
属性:
keyColumn:主键字段
keyProperty:实体类中的属性(与主键字段对应)
resultType:主键数据类型
resultMap:用于配置实体类属性与数据库表字段一一对应的
type:要映射的java对象类型
id:唯一标识名称,通过id引用该resultMap
order:在insert语句执行前,还是执行后获取主键值。BEFORE:在insert执行前;AFTER:在insert语句执行后
说明:直接在insert标签中增加属性的方式,只适合于支持自动增长主键类型的数据库,比如mysql。
3.注意事项:java程序代码执行成功,但是数据库中并没有新增记录。原因是没有提交事务,在对数据库的更新操作中(增、删、改)要求提交事务。
自动提交的特点,只要操作一完成,立即提交。如果在同一个方法中,有多个数据库操作,需要使用手动提交的方式。
(方式一)创建SqlSession,指定自动提交事务。true:自动提交;false:不提交。默认是false
SqlSession sqlSession = sqlSessionFactory.openSession(true);
(方式二)手动提交事务
sqlSession.commit();
4 mapper代理开发方法【掌握】
从入门程序开始,一直使用的方式,即mapper代理开发的方法。特点:
1. 在开发的时候,只需要编写持久层的接口,和持久层接口映射文件(mapper映射文件)。
2. 在执行的时候,mybatis框架通过动态代理生成接口的代理对象。
3. 总结mapper代理开发原则【记住】
1. mapper映射文件中namespace属性值,必须是mapper接口的全限定名称
2. mapper映射文件中sql语句标签的声明,与mapper接口中接口方法声明一致
2.1.sql语句标签中resultType属性指定的返回值类型,与mapper接口方法返回值类型一致。(如果接口方法返回的是集合list,则resultType指定的是list中存放的类型)
2.2.sql语句标签中的id属性值,与mapper接口方法名称一致
2.3.sql语句标签中的parameterType属性指定的类型,与mapper接口方法的形参类型一致
day3
一、mybaits连接池
1.JNDI:java的名称服务,用于从容器中获取数据库的连接(tomcat)
2.POOLED:使用连接池技术
3.UNPOOLED:不使用连接池技术(相当于原生的jdbc操作)
二、mybatis事务控制
1.手动提交
2.自动提交
3.mybatis框架的事务,底层都还是jdbc的事务操作
三、mybatis动态sql
1.动态sql案例(需求:根据用户名称和性别查询用户)
1.声明mapper接口方法
2.配置mapper映射文件
2.if标签
作用:判断传入的参数情况,拼装sql语句片段
<!--根据用户名称和性别查询用户-->
<select id="findUserByNameAndSex"parameterType="user"resultType="user">
select * from `user`
where <!--username like #{username} and sex=#{sex}-->
<!--if:判断用户名称不为空,且不为空字符串,则作为查询条件-->
<if test="username !=null and username !=''">
username like #{username}
</if>
<!--if:判断用户性别不为空,且不为空字符串,则作为查询条件-->
<if test="sex !=null and sex !=''">
and sex=#{sex}
</if>
</select>
3.where标签
作用:
1.相当于sql语句中的where关键字
2.根据传入的参数情况,智能的去掉多余的and,or关键字
3.根据传入的参数情况,智能的去掉多余的where关键字
<!--根据用户名称和性别查询用户-->
<select id="findUserByNameAndSex"parameterType="user"resultType="user">
select * from `user`
<!-- where username like #{username} and sex=#{sex}-->
<where>
<!--if:判断用户名称不为空,且不为空字符串,则作为查询条件-->
<if test="username !=null and username !=''">
username like #{username}
</if>
<!--if:判断用户性别不为空,且不为空字符串,则作为查询条件-->
<if test="sex !=null and sex !=''">
and sex=#{sex}
</if>
</where> </select>
4.set标签:
作用:
1.相当于sql语句中的set关键字
2.根据传入的参数情况,智能的去掉最后一个多余的逗号
<!-- 动态修改用户数据 -->
<update id="dynamicUpdateUser"parameterType="user">
update `user`
<!-- set username='小李飞刀',sex='2' where id=2 -->
<set>
<if test="username != null and username !=''">
username=#{username},
</if>
<if test="sex != null and sex !=''">
sex=#{sex},
</if>
</set> <where>
id=#{id}
</where>
</update>
5.sql(include)标签:
作用:
1.提取公共的sql语句片段
<!--sql:提取公共的sql语句片段,说明:
id:唯一标识名称,通过id引用该sql片段
-->
<sql id="select_orders_list">
o.id,o.user_id,o.number,o.createtime,o.note
</sql> <!--查询全部订单数据,使用resultType实现-->
<select id="findAllOrders"resultType="cn.itheima.po.Orders">
<!--include:引用sql语句片段,说明:
refid:sql语句片段的id属性值
-->
select <include refid="select_orders_list"></include> from orders o
</select>
6.foreach标签:
作用:
1.循环处理参数集合(list,数组)
<!-- 批量新增用户-->
<insert id="batchAddUsers"parameterType="list">
insert into `user`(username,birthday,sex,address)
values
<!-- foreach:循环处理参数集合
collection:参数集合,这里是list(固定写法)
item:当前遍历的对象
separator:指定分割符
-->
<foreach collection="list"item="u"separator=",">
(#{u.username},#{u.birthday},#{u.sex},#{u.address})
</foreach>
<!-- ('用户1','2018-07-08','1','地址1'),('用户2','2018-07-08','1','地址2') -->
</insert>
四、mybatis关联查询
1.关联关系分类:
一对一关联关系:人和身份证关系,【双向的】一对一关系
一对多关联关系:用户和订单的关系
多对多关联关系:用户和角色
2.分析用户订单数据模型:
第一步:先确定单表有什么字段
第二步:找出关联字段
第三步:结合业务需求确定表的关系
3.一对一关联查询:
实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件
通过ResultType实现:
关键步骤:编写一个实体类,包含sql语句中的字段对应属性
通过ResultMap实现(<association/>):
关键步骤:在实体类之间建立关系,建立订单到用户的一对一关系
<!-- 配置订单到用户的一对一关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="orders"id="ordersUsersResultMap">
<!-- 配置订单主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置订单的普通字段对应关系 -->
<result column="user_id"property="userId"/>
<result column="number"property="number"/>
<result column="createtime"property="createtime"/>
<result column="note"property="note"/> <!-- association:配置一对一关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(必须要指定)
-->
<association property="user"javaType="User">
<!-- 配置用户的主键字段对应关系 -->
<id column="user_id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="address"property="address"/>
</association> </resultMap> <!-- 查询全部订单数据,并且关联查询订单所属的用户数据(resultMap)-->
<select id="findAllOrdersAndUserResultMap"resultMap="ordersUsersResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
orders o
LEFT JOIN `user` u ON o.user_id = u.id
</select>
4.一对多关联查询:
实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件
思考题:一对多能不能使用ResultType实现? 不能使用ResultType实现
使用ResultMap实现(<collection/>):
关键步骤:在实体类之间建立关系,建立用户到订单的一对多关系
<!-- 配置用户到订单的一对多关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="user"id="usersOrdersResultMap">
<!-- 配置用户的主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="birthday"property="birthday"/>
<result column="sex"property="sex"/>
<result column="address"property="address"/> <!-- collection:配置一对多关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(可以指定,可以不指定,建议都指定)
ofType:指定集合中存放的类型(必须要指定)
-->
<collection property="ordersList"javaType="List"ofType="Orders">
<!-- 配置订单的主键对应关系 -->
<id column="oid"property="id"/>
<!-- 配置订单普通字段对应关系 -->
<result column="number"property="number"/>
<result column="createtime"property="createtime"/>
</collection> </resultMap> <!-- 查询全部用户数据,并且关联查询出用户的所有订单数据 -->
<select id="findAllUsersAndOrders"resultMap="usersOrdersResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime
FROM
`user` u
LEFT JOIN orders o ON u.id = o.user_id
</select>
5.多对多关联查询:通过中间表看成两个一对多关联关系
需求:查询用户数据,并且关联查询出用户的角色数据
实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件
关键步骤:在实体类之间建立关系,建立用户到角色的一对多关系
<!-- 配置用户到角色的一对多关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="user"id="usersRolesResultMap">
<!-- 配置用户的主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="birthday"property="birthday"/>
<result column="sex"property="sex"/>
<result column="address"property="address"/> <!-- collection:配置一对多关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(可以指定,可以不指定,建议都指定)
ofType:指定集合中存放的类型(必须要指定)
-->
<collection property="roleList"javaType="List"ofType="Role">
<!-- 配置订单的主键对应关系 -->
<id column="role_id"property="roleId"/>
<!-- 配置订单普通字段对应关系 -->
<result column="role_name"property="roleName"/>
</collection> </resultMap> <!-- 查询用户数据,并且关联查询用户的所有角色数据-->
<select id="findUsersAndRoles"resultMap="usersRolesResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
r.role_id,
r.role_name
FROM
`user` u
INNER JOIN user_role ur ON u.id = ur.user_id
INNER JOIN role r ON ur.role_id = r.role_id
</select>
day4
一、mybatis延迟加载
1.什么是延迟加载?
延迟加载,叫做懒加载,按需加载。
它的特点关联查询中,分步骤实现查询(每一步都是单表操作)
2.延迟加载案例演示:
查询订单数据,并且关联查询出订单所属的用户数据。采用延迟加载的方式实现。
实现步骤:
第一步:只从订单表查询订单数据
第二步:在需要的时候,在查询用户表的数据
第三步:配置mybatis框架,开启延迟加载
延迟加载的注意事项:toString方法和debug调试模式看不到延迟加载的效果
3.一对多关联查询的延迟加载方式实现:
第一步:单表查询用户数据
第二步:在需要的时候,再查询订单表的数据
第三步:配置mybatis框架,开启延迟加载
二、mybatis缓存
1.一级缓存:sqlSession范围的缓存,一级缓存本身就已经存在,不需要关心
2.二级缓存:mapper级别级别,在多个sqlSession之间可以共享数据
第一步:需要配置sqlMapConfig.xml,开启二级缓存
第二步:序列化Seriallizable,实体类对象需要实现序列化
第三步:在mapper映射文件,还需要明确是否使用缓存
说明:mybatis的二级缓存只做了解,在企业项目中不推荐使用。原因是mybatis的缓存
不能实现【细粒度】的控制。实际项目中我们会考虑使用像redis中间件
三、mybatis注解开发【了解】
1.注解基本操作(CRUD操作):
查询:@Select
修改:@Update
删除:@Delete
新增:@Insert
获取数据库维护的主键值:
@SelectKey
2.注解高级操作(关联查询):
@Results注解:相当于xml文件中的<ResultMap/>标签
@Result注解:相当于<ResultMap/>的子标签<id/>和<result/>
@One注解:配置一对一关联关系,相当于xml中的<association/>,可以实现延迟加载
@Many注解:配置一对多关联关系,相当于xml中的<collection/>标签,可以实现延迟加载
延迟加载方式实现:一对一关联查询的方式:
实现步骤:
第一步:只从订单表查询数据
第二步:在需要的时候,查询用户表数据
第三步:在sqlMapConfig.xml中,配置延迟加载
延迟加载方式实现:一对多关联查询:
需求:查询全部用户数据,并且关联查询出用户的全部订单数据。采用延迟加载的方式实现
实现步骤:
第一步:只查询用户表数据
第二步:在需要的时候,查询订单表的数据
第三步:在sqlMapConfig.xml中,配置延迟加载
mybatis技术总结的更多相关文章
- 2017.2.9 深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二)-----配置文件详解
深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二) ------配置文件详解 8.2 MyBatis-Spring应用 8.2.1 概述 本文主要讲述通过注解配置MyBa ...
- Mybatis技术内幕(一)——整体架构概览
Mybatis技术内幕(一)--整体架构概览 Mybatis的整体架构分为三层,分别是基础支持层.核心处理层和接口层. 如图所示: 一.基础支持层 基础支持层包含整个Mybatis的基础模块,这些模块 ...
- 2MyBatis入门--深入浅出MyBatis技术原理与实践(笔记)
什么是 MyBatis ? MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- Mybatis技术原理理——整体流程理解
前言:2018年,是最杂乱的一年!所以你看我的博客,是不是很空! 网上有很多关于Mybatis原理介绍的博文,这里介绍两篇我个人很推荐的博文 Mybatis3.4.x技术内幕和 MyBaits源码分析 ...
- 深入理解Mybatis技术与原理
目录 第1章 Mybatis简介 1.1 传统的JDBC编程 1.2 ORM模型 1.4 MyBatis 1.5 什么时候用MyBatis 第2章 MyBatis入门 2.2 MyBatis构成 2. ...
- 《深入浅出MyBatis技术原理与实战》——7. 插件
在第6章讨论了四大运行对象的运行过程,在Configuration对象的创建方法里我们看到了MyBatis用责任链去封装它们. 7.1 插件接口 在MyBatis中使用插件,我们必须使用接口Inter ...
- 《深入浅出MyBatis技术原理与实战》——6. MyBatis的解析和运行原理
MyBatis的运行分为两大部分,第一部分是读取配置文件缓存到Configuration对象,用以创建SqlSessionFactory,第二部分是SqlSession的执行过程. 6.1 涉及的技术 ...
- 3MyBatis配置--深入浅出MyBatis技术原理与实践(笔记)
XML 映射配置文件 configuration 配置 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFact ...
- 《深入浅出MyBatis技术原理与实战》——4. 映射器,5. 动态SQL
4.1 映射器的主要元素 4.2 select元素 4.2.2 简易数据类型的例子 例如,我们需要统计一个姓氏的用户数量.应该把姓氏作为参数传递,而将结果设置为整型返回给调用者,如: 4.2.3 自动 ...
随机推荐
- java ->多线程_线程池
线程池概念 线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源. 我们详细的解释一下为什么要使用线程池?(程序优化) 在jav ...
- 真香警告!扩展 swagger支持文档自动列举所有枚举值
承接上篇文章 <一站式解决使用枚举的各种痛点> 文章最后提到:在使用 swagger 来编写接口文档时,需要告诉前端枚举类型有哪些取值,每次增加取值之后,不仅要改代码,还要找到对应的取值在 ...
- python之模块、类、对象
模块就像字典 字典是python中唯一映射关系,它用一个事物对应另外一个事物,也就是所谓的key->value. 模块包含一些变量和函数,可以导入,并且可以用点(·)来操作访问变量和函数. 记住 ...
- XCode Interface Builder开发——2
XCode Interface Builder开发--2 简单的练手项目--仿苹果自备的计算器 简介 制作一个简易功能的计算器并非难事,但是其中要考虑的不同情况却仍有许多,稍不留神就会踩坑. 例如: ...
- Java Mail 发送带有附件的邮件
1.小编用的是163邮箱发送邮件,所以要先登录163邮箱开启POP3/SMTP/IMAP服务方法: 2.下载所需的java-mail 包 https://maven.java.net/content/ ...
- zookeeper实现分布式锁总结,看这一篇足矣(设计模式应用实战)
分布式锁纵观网络各种各样的帖子层出不穷,笔者查阅很多资料发现一个问题,有些文章只写原理并没有具体实现,有些文章虽然写了实现但是并不全面 借这个周末给大家做一个总结,代码拿来就可以用并且每一种实现都经过 ...
- Robot Framework(2)- 快速安装
如果你还想从头学起Robot Framework,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1770899.html 安装RF cmd ...
- CustomerDAO及CustomerImpl的实现 & CustomerImpl的单元测试
BaseDAO:封装了针对于数据表的操作,提供通用的方法,完成后续针对具体表的逻辑 CustomerDAO:此接口用于规范 针对customers表的常用操作 CustomerDAOImpl:继承Ba ...
- ## H5 canvas画图白板踩坑
最近接手了一个小型的H5,最主要的功能大概就是拍照上传和canvas画板了. 主要是记录一下自己菜到像傻子一样的技术. 1.canvas画板隔空打牛!画布越往上部分错位距离越小,越往下距离越大. 2. ...
- (易忘篇)java基本语法难点1
switch后面使用的表达式可以是哪些数据类型 byte.short.char.int.枚举类型变量.String类型. 如何从控制台获取String和int型的变量,并输出 // 以下只关注重要点的 ...