聊天宝、多闪、马桶MT围剿微信,谁会更有胜算?
2019年1月15日,这注定是一个载入互联网发展历史的重要时刻。仅仅一天时间内,三家企业接连召开社交产品的发布会,并且各自都能自圆其说地讲出自己的优势,这让不少吃瓜群众看着都替微信捏了一把汗。
2018年,今日头条的主角光环愈加强大了。尽管目前今日头条的母公司字节跳动尚未上市,其实际营收能力和利润能力与BAT也还存在一定的距离,但字节跳动想要赶超BAT的野心已经昭昭了。
近日,据多家媒体的报道显示,字节跳动将上线一款年度级别的社交产品飞聊,并且与抖音一样的是,这款名为飞聊的社交产品将不会被内嵌在今日头条APP内,而是以独立APP形式推出。
通过站长平台工具的域名whois查询功能,可以根据网传字节跳动收购的域名“flipchat.cn”查询到,其联系人的邮箱后缀确实是字节跳动旗下的域名“bytedance.com”。此外,今日头条也完全没有否认——很显然,今日头条即将推出社交产品对垒腾讯旗下微信,已经是件板上钉钉的事情了。
一时间,互联网行业各界人士对此热议不断,就连欢聚时代CEO李学凌也忍不住直言支持今日头条,认为张一鸣的飞聊拥有太多成功的因素了。
从免费邀请入驻到收取佣金,再到如今屡次提升佣金收取比例,美团外卖又做出了一个引发争议的决定。
近日,美团外卖对商家下达了一条“新命令”:平台对商户收取的佣金,从原来的18%上调到了22%,增加了4%的佣金收取。简单来说,商家在美团平台上每挣100元,美团就要从中抽取22元。高佣金比例让商家很大一部分利润都要贡献给外卖平台,这自然就引起了很多商家的不满,甚至有些商家最终选择逃离美团外卖。那么,明明知道提升佣金会引起商家不满,美团外卖为什么还会要增加佣金比例呢?在美团的这个超级平台里,外卖只是其中的一部分,但美团超级平台的未来又会是怎样呢?透过此次美团外卖上涨佣金这件事情,这些问题或许都可以找到答案。
与此前共享单车的狂欢相比,今年的共享单车似乎都不好过,尤其是近日陷入了押金风波的ofo。
从迅速崛起到走向衰落,ofo在这三年半的时间里可谓是度过了共享单车的春夏秋冬四季。如今据报道显示,已经有超过千万人在ofo的App上排队退押金,创始人戴威还被列入“老赖”名单,留给ofo的时间真是不多了。
从一个令所有互联网从业者都为之狂欢的独角兽,到被千万用户追着退押金,ofo究竟为什么会出现这样的情况?在当下的这种危机情况下,ofo还有机会成为下一个滴滴吗?如果没有别的出路,ofo恐怕将难以为继,至少共享单车ofo的春天已经很难再次到来了。
在2018年出现多次危机后,2019年的苹果依旧没有获得一个好开头。
1月7日,在2019年CES即将开幕之际,苹果突然宣布与其死对头三星达成深度的内容合作,iTunes电影和电视内容将可以在三星电视上进行播放。一时间,这一消息引发全球科技行业的热议。
对于以“封闭”闻名的苹果来说,苹果会与三星进行内容合作,这无疑是一个艰难的决定。这不仅释放出苹果想要力求开放的态度,同时也说明苹果的发展难题比想象中或许还要复杂。


MyBatis-Plus 是一个 MyBatis 的增强工具,旨在简化开发过程,提供更便捷的数据库操作方式。在 MyBatis-Plus 中,XML 配置文件扮演着重要的角色,它允许开发者定义 SQL 语句、映射结果集以及配置各种数据库操作。本文将详细介绍 MyBatis-Plus XML 配置文件中的各种标签和功能,从基础的查询、插入、更新、删除操作,到高级的动态 SQL、结果映射和批量操作,帮助你全面掌握 MyBatis-Plus 的 XML 配置技巧,提升开发效率。(主要就是因为 mybatis-plus 封装的太好了,能不写sql就不写,到写的时候都忘记了…)
MyBatis-Plus 官网 : Mybatis-Plus
MyBatis 官网 : Mybatis中文官网
SQL 优化 :[笔记] SQL数据库优化实战 : SQL 全面优化本文总结了SQL数据库优化的实战技巧,包括字段选择、索引策略、查询语... - 掘金
一. 基础标签
1. select 标签
xml 代码解读复制代码<select id="getById" resultType="User" parameterType="long">
SELECT * FROM user WHERE id = #{id}
select>
用于查询操作,最基本的查询标签。
id
: 对应 Mapper 接口中的方法名。resultType
: 返回的结果类型。parameterType
: 参数类型(可选)。
2. insert 标签
xml 代码解读复制代码<insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (username, age) VALUES (#{username}, #{age})
insert>
用于插入操作。
useGeneratedKeys
: 是否使用自增主键。keyProperty
: 自增主键对应的属性名。
3. update 标签
xml 代码解读复制代码<update id="update" parameterType="User">
UPDATE user SET username = #{username} WHERE id = #{id}
update>
用于更新操作。
parameterType
: 参数类型。
4. delete 标签
xml 代码解读复制代码<delete id="deleteById" parameterType="long">
DELETE FROM user WHERE id = #{id}
delete>
用于删除操作。
parameterType
: 参数类型。
二. 动态 SQL 标签
1. if 标签
xml 代码解读复制代码<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
if>
条件判断,当 test 属性中的条件成立时,才会将其包含的 SQL 片段拼接到最终的 SQL 中。
test
: 判断条件,支持 OGNL 表达式
2. choose-when-otherwise 标签
xml 代码解读复制代码<choose>
<when test="status != null">
AND status = #{status}
when>
<when test="type != null">
AND type = #{type}
when>
<otherwise>
AND create_time > SYSDATE
otherwise>
choose>
类似 Java 中的
switch
语句,只会执行一个条件。
3. where 标签
xml 代码解读复制代码<where>
<if test="username != null">
AND username = #{username}
if>
<if test="age != null">
AND age >= #{age}
if>
where>
自动处理
WHERE
子句,会自动去除多余的AND
或OR
。
4. set 标签
xml 代码解读复制代码<update id="updateUser">
UPDATE user
<set>
<if test="username != null">username = #{username},if>
<if test="age != null">age = #{age},if>
set>
WHERE id = #{id}
update>
用在
UPDATE
语句中,自动处理SET
关键字和逗号。
5. trim 标签
xml 代码解读复制代码<trim prefix="WHERE" prefixOverrides="AND|OR" suffix=")" suffixOverrides=",">
<if test="username != null">
AND username = #{username},
if>
trim>
更灵活的前缀/后缀处理。
prefix
: 给整个语句增加前缀。prefixOverrides
: 去除整个语句前面的关键字或字符。suffix
: 给整个语句增加后缀。suffixOverrides
: 去除整个语句后面的关键字或字符。- 运行结果 :
WHERE username = #{username}
。
6. foreach 标签
xml 代码解读复制代码<foreach collection="list" item="item" index="index" open="(" separator="," close=")">
#{item}
foreach>
循环遍历集合或数组。
collection
: 要遍历的集合或数组(list
、array
、map
等)。item
: 当前遍历的元素。index
: 当前遍历的索引。open
: 开始字符。separator
: 分隔符。close
: 结束字符。
三. 高级映射
1. resultMap 标签
xml 代码解读复制代码<resultMap id="UserResultMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="user_name"/>
<association property="profile" javaType="UserProfile">
<id property="id" column="profile_id"/>
<result property="address" column="address"/>
association>
<collection property="roles" ofType="Role">
<id property="id" column="role_id"/>
<result property="roleName" column="role_name"/>
collection>
resultMap>
自定义结果映射关系。
标签
id="UserResultMap"
: 定义了这个的唯一标识符,以便在其他地方引用它。
type="User"
: 指定了这个所映射的目标类型,这里是
User
类。
- 主键映射
: 映射数据库表中的
user_id
列到User
对象的id
属性上。标签通常用于主键映射,有助于提高 MyBatis 在处理关联关系时的性能。
- 普通属性映射
: 将数据库表中的
user_name
列映射到User
对象的username
属性上。标签用于普通属性的映射。
- 一对一关系 (
)
property="profile" javaType="UserProfile"
: 表示User
对象与UserProfile
对象之间存在一对一的关系,并且将查询结果映射到User
对象的profile
属性上。
: 映射
UserProfile
对象的主键。: 映射
UserProfile
对象的address
属性。
- 一对多关系 (
)
property="roles" ofType="Role"
: 表示User
对象与多个Role
对象之间存在一对多的关系,并且将查询结果映射到User
对象的roles
属性上。
: 映射每个
Role
对象的主键。: 映射每个
Role
对象的roleName
属性。
2. sql 标签
xml 代码解读复制代码
<sql id="Base_Column_List">
id, username, age, email, create_time
sql>
<select id="selectById">
SELECT <include refid="Base_Column_List"/> FROM user
select>
定义可重用的 SQL 片段。
四. 特殊功能
1. bind 标签
xml 代码解读复制代码<select id="selectByName">
<bind name="pattern" value="'%' + name + '%'"/>
SELECT * FROM user WHERE username LIKE #{pattern}
select>
创建一个变量并绑定到上下文中。
2. 特殊字符:CDATA 区段(关联 XML 实体)
xml 代码解读复制代码<select id="getUsers">
SELECT * FROM user
WHERE age = ]]> #{minAge}
select>
处理特殊字符。
3. 特殊字符:XML 实体(关联 CDATA 区段)
- 预定义的 XML 实体
xml 代码解读复制代码<select id="getUsers">
SELECT * FROM user
WHERE age >= #{minAge}
select>
预定义的 XML 实体
<
对应<
。>
对应>
。&
对应&
。"
对应"
。'
对应'
。
- 自定义实体
xml 代码解读复制代码
example [
myEntity "This is a custom entity">
]>
<example>
Here is the custom entity: &myEntity;
example>
<example>
Here is the custom entity: This is a custom entity
example>
自定义实体允许你在XML文档中定义一些简短的替代符号,这些符号可以在文档的不同部分引用。
代码解释
: 这是一个DOCTYPE声明,用于定义当前文档的类型和结构。在这个例子中,
example
是根元素名称,方括号[]
内包含了自定义实体的定义。: 定义了一个名为
myEntity
的自定义实体。myEntity
是一个标识符,"This is a custom entity"
是这个实体的实际值。在文档的其他地方,你可以通过&myEntity;
来引用这个实体。: 根元素,包含文档的主要内容。
Here is the custom entity: &myEntity;
: 在这个元素的内容中,使用了之前定义的自定义实体&myEntity;
。当解析器读取到这个标记时,会自动将其替换为实体的实际值"This is a custom entity"
。
渲染结果
当你解析这个XML文档时,解析器会将
&myEntity;
替换为其定义的值。最终的结果将是:
xml代码解读复制代码<example> Here is the custom entity: This is a custom entity example>
五. 实用场景示例
1. 动态表关联
xml 代码解读复制代码<select id="getUserDetails" resultMap="UserDetailMap">
SELECT u.*
FROM user u
<if test="includeProfile">
LEFT JOIN user_profile up ON u.id = up.user_id
if>
<if test="includeRoles">
LEFT JOIN user_role ur ON u.id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.id
if>
WHERE u.id = #{userId}
select>
根据条件决定是否关联其他表。
动态地从多个表中获取用户详细信息。
代码解析
: 定义了这个查询的唯一标识符,可以在Java代码中通过这个ID来调用该查询,并指定了结果映射(
resultMap
)。
SELECT u.* FROM user u
: 选择了user
表中的所有列,并给这个表起了一个别名u
。动态关联用户资料表:
xml代码解读复制代码<if test="includeProfile"> LEFT JOIN user_profile up ON u.id = up.user_id if>
- 检查传入的参数
includeProfile
是否为true
。如果为true
,则执行内部的SQL片段。动态关联角色表:
xml代码解读复制代码<if test="includeRoles"> LEFT JOIN user_role ur ON u.id = ur.user_id LEFT JOIN role r ON ur.role_id = r.id if>
- 检查传入的参数
includeRoles
是否为true
。如果为true
,则执行内部的SQL片段。
WHERE u.id = #{userId}
: 这条语句用于过滤结果,只返回指定用户ID的数据。
调用
传参:
includeProfile = true
includeRoles = true
userId = 1
生成的SQL:
sql代码解读复制代码SELECT u.* FROM user u LEFT JOIN user_profile up ON u.id = up.user_id LEFT JOIN user_role ur ON u.id = ur.user_id LEFT JOIN role r ON ur.role_id = r.id WHERE u.id
2. 批量操作优化
xml 代码解读复制代码
<update id="batchUpdate">
UPDATE user
<trim prefix="SET" suffixOverrides=",">
<trim prefix="username = CASE" suffix="END,">
<foreach collection="list" item="item">
WHEN id = #{item.id} THEN #{item.username}
foreach>
trim>
trim>
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id}
foreach>
update>
适用于大量数据的批量操作。
批量更新用户表中的数据。
代码解析
: 定义了这个更新操作的唯一标识符,可以在Java代码中通过这个ID来调用该更新操作。
UPDATE user
: 指定了要更新的表名,这里是user
表。第一个
标签:
xml代码解读复制代码<trim prefix="SET" suffixOverrides=","> ... trim>
prefix="SET"
: 在生成的SQL语句前添加SET
关键字。suffixOverrides=","
: 自动移除生成的SQL语句末尾多余的逗号。第二个
标签:
xml代码解读复制代码<trim prefix="username = CASE" suffix="END,"> ... trim>
prefix="username = CASE"
: 在生成的SQL语句前添加username = CASE
。suffix="END,"
: 在生成的SQL语句后添加END,
。嵌套的
标签:
xml代码解读复制代码<foreach collection="list" item="item"> WHEN id = #{item.id} THEN #{item.username} foreach>
collection="list"
: 指定要遍历的集合,这里假设传入的参数是一个包含多个用户的列表。item="item"
: 定义当前遍历项的变量名,这里是item
。
WHERE id IN ...
:
xml代码解读复制代码WHERE id IN <foreach collection="list" item="item" open="(" separator="," close=")"> #{item.id} foreach>
- 这部分使用另一个
标签来生成
WHERE id IN (...)
子句。
整体效果
假设你传入的参数是一个包含两个用户的列表,每个用户都有一个
id
和一个新的username
值:
java代码解读复制代码List
userList = new ArrayList<>(); userList.add(new User(1, "newUsername1")); userList.add(new User(2, "newUsername2"));生成的最终SQL语句将会是:
sql代码解读复制代码UPDATE user SET username = CASE WHEN id = 1 THEN 'newUsername1' WHEN id = 2 THEN 'newUsername2' END WHERE id IN (1, 2);
六. 最佳实践
1. 性能优化
- 避免使用
SELECT *
,只查询需要的字段。 - 合理使用索引。
- 大量数据操作时使用批量处理。
- 适当使用缓存。
2. 安全性
- 使用
#{}
而不是${}
来防止 SQL 注入。 - 参数校验。
- 敏感数据加密。
3. 可维护性
- 使用统一的命名规范
- 添加适当的注释
- 复杂 SQL 进行模块化处理
- 保持代码整洁和可读性
七. 注意事项
#{}
和${}
的区别:#{}
会进行预编译,防止 SQL 注入。${}
直接替换,有 SQL 注入风险。
- 动态 SQL 的顺序很重要,要注意逻辑的先后顺序。
- 批量操作时注意数据库的性能限制。
- 复杂查询建议使用
resultMap
而不是resultType
。 - 对于大量重复的 SQL 片段,建议使用
sql
标签复用。
评论记录:
回复评论: