范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

开源Java真正智慧的ORM框架,兼具HibernateMyBatis双重优点

  一飞开源,介绍创意、新奇、有趣、实用的免费开源应用、系统、软件、硬件及技术,一个探索、发现、分享、使用与互动交流的开源技术社区平台。致力于打造活力开源社区,共建开源新生态!一、开源项目简介sqltoy-orm是什么
  sqltoy-orm是比hibernate+myBatis(plus)更加贴合项目的orm框架(依赖spring),具有jpa式的对象CRUD的同时具有比myBatis(plus)更直观简洁性能强大的查询功能,越复杂优势越凸显。 支持以下数据库:oracle11g+、db2(9.5+)、sqlserver2012+、postgresql9.5+、mysql5.6+(mariadb/innosql)sqlite、H2DM达梦数据库、kingbaseelasticsearch 只支持查询,版本支持5.7+版本,建议使用7.3以上版本clickhouse、StarRocks、greenplum、impala(kudu)oceanBase、polardb、guassdb、tidbmongodb (只支持查询)其他数据库支持基于jdbc的sql执行(查询和自定义sql的执行)二、开源协议
  使用Apache-2.0开源协议三、界面展示
  技术架构
  架构原则:sqltoy-orm是协助开发者的工具之一,目标是要解决99.5%的问题而不是覆盖100%的问题(目前从复杂的ERP项目、数据分析报表项目的实践角度看基本100%覆盖)。
  四、功能概述
  Java真正智慧的ORM框架!支持mysql、oracle、postgresql、sqlserver、db2、dm、mongodb、elasticsearch、tidb、kingbase、oceanbase、guassdb、greenplum、StarRocks、impala(kudu)、clickhouse、sqlite、h2、polardb。
  sqltoy-orm是基于java语言开发的,兼有hibernate面向对象操作和myBatis灵活查询的优点,同时更贴切项目、更贴切开发者的一个关系型数据库ORM框架,支持oracle、mysql、postgresql、sqlserver、db2、sqlite、sybase iq、elasticsearch、mongodb等数据库。
  与sqltoy-orm配套的有一个quickvo工具,协助通过数据库表产生POJO对象类。Quickvo工具摈弃了hibernate-tools工具的不足(如模块化配置、主键策略配置、级联加载、修改、删除的逻辑),可以让开发者通过配置文件进行灵活控制POJO的生成,而不用担心自己对POJO类的修改被覆盖。
  sqltoy最大的特点在于贴切项目、了解开发者,试图实实在在的帮助开发者简化数据库交互过程中的大量看似很重要其实是机械的重复工作,同时sqltoy将大量第一手项目最佳实践模式抽象成工具带给开发者。
  sqltoy究竟能给你带来什么?有别于hibernate的增删改(含批量和级联)内部实现,hibernate修改对象个别属性是不是要先load后修改防止其他字段被置为null?高并发大集群下面就会冲掉别人修改的数据。堪称最为优雅的动态sql查询写法,一眼就可以看明白sql的业务含义,后期维护更容易,更容易进行sql优化和调整。提供快速分页查询可能实现先分页后关联,减少关联数据规模。让你极大减少表关联、让sql更简洁清晰并提升性能的缓存翻译功能。让你不需要太牛的sql能力实现行转列、列转行。提供多重分组汇总求平均的功能(算法和sql的结合,以强补弱,简单而优雅)让分页查询可以只需1.45次,你的分页是不是2次查询(一次查总记录数、一次查实际记录)?支持并行查询特性(4.17.13版本支持并行分页查询)提供分库分表sharding功能,为高性能、分布式场景奠定基础。最大程度实现跨数据库能力,提供不同数据库函数动态替换,尤其针对软件产品一个sql就可以适应不同数据库。Sql语句支持注释,即客户端调试好即可copy进来。机理是加载sql时剔除注释,但会保留/*+--hint--*/形式的数据库自身优化性注释。五、技术选型1、基于Java语言开发2. 快速特点说明2.1 对象操作跟jpa类似并有针对性加强(包括级联)通过quickvo工具从数据库生成对应的POJO,引入sqlltoy自带的SqlToyLazyDao即可完成全部操作   StaffInfoVO staffInfo = new StaffInfoVO();     //保存    sqlToyLazyDao.save(staffInfo);    //删除    sqlToyLazyDao.delete(new StaffInfoVO("S2007"));     //public Long update(Serializable entity, String... forceUpdateProps);    // 这里对photo 属性进行强制修改,其他为null自动会跳过    sqlToyLazyDao.update(staffInfo, "photo");     //深度修改,不管是否null全部字段修改    sqlToyLazyDao.updateDeeply(staffInfo);     List staffList = new ArrayList();    StaffInfoVO staffInfo = new StaffInfoVO();    StaffInfoVO staffInfo1 = new StaffInfoVO();    staffList.add(staffInfo);    staffList.add(staffInfo1);    //批量保存或修改    sqlToyLazyDao.saveOrUpdateAll(staffList);    //批量保存    sqlToyLazyDao.saveAll(staffList);    ...............    sqlToyLazyDao.loadByIds(StaffInfoVO.class,"S2007")    //唯一性验证    sqlToyLazyDao.isUnique(staffInfo, "staffCode");2.2 支持代码中对象查询sqltoy 中统一的规则是代码中可以直接传sql也可以是对应xml文件中的sqlId/**  * @todo 通过对象传参数,简化paramName[],paramValue[] 模式传参  * @param   * @param sqlOrNamedSql 可以是具体sql也可以是对应xml中的sqlId  * @param entity        通过对象传参数,并按对象类型返回结果  */  public  List findBySql(final String sqlOrNamedSql, final T entity);基于对象单表查询,并带缓存翻译public Page findStaff(Page pageModel, StaffInfoVO staffInfoVO) {      // sql可以直接在代码中编写,复杂sql建议在xml中定义      // 单表entity查询场景下sql字段可以写成java类的属性名称      return findPageEntity(pageModel, StaffInfoVO.class, EntityQuery.create() 	.where("#[staffName like :staffName]#[and createTime>=:beginDate]#[and createTime<=:endDate]") 	.values(staffInfoVO)); }对象式查询后修改或删除//演示代码中非直接sql模式设置条件模式进行记录修改 public Long updateByQuery() {      return sqlToyLazyDao.updateByQuery(StaffInfoVO.class, 		EntityUpdate.create().set("createBy", "S0001")                      .where("staffName like ?").values("张")); }  //代码中非直接sql模式设置条件模式进行记录删除 sqlToyLazyDao.deleteByQuery(StaffInfoVO.class, EntityQuery.create().where("status=?").values(0));2.3 极致朴素的sql编写方式sqltoy 的写法(一眼就看明白sql的本意,后面变更调整也非常便捷,copy到数据库客户端里稍做出来即可执行)sqltoy条件组织原理很简单: 如 #[order_id=:orderId] 等于if(:orderId<>null) sql.append(order_id=:orderId);#[]内只要有一个参数为null即剔除支持多层嵌套:如 #[and t.order_id=:orderId #[and t.order_type=:orderType]]条件判断保留#[@if(:param>=xx ||:param<=xx1) sql语句] 这种@if()高度灵活模式,为特殊复杂场景下提供便利//1、 条件值处理跟具体sql分离 //2、 将条件值前置通过filters 定义的通用方法加工规整(大多数是不需要额外处理的)            =:beginAndEndDate[0]] 		  #[and t.TRANS_DATE<:beginAndEndDate[1]]     	]]> 同等功能mybatis写法2.4 天然防止sql注入,执行过程:假设sql语句如下select 	* from sqltoy_device_order_info t  where #[t.ORGAN_ID in (:authedOrganIds)]       #[and t.TRANS_DATE>=:beginDate]       #[and t.TRANS_DATE<:endDate] java调用过程sqlToyLazyDao.findBySql(sql, MapKit.keys("authedOrganIds","beginDate", "endDate").values(authedOrganIdAry,beginDate,null),                           DeviceOrderInfoVO.class);最终执行的sql是这样的:select 	* from sqltoy_device_order_info t  where t.ORDER_ID=?       and t.ORGAN_ID in (?,?,?)       and t.TRANS_DATE>=?	然后通过: pst.set(index,value) 设置条件值2.5 最为极致的分页2.5.1 分页特点说明1、快速分页:@fast() 实现先取单页数据然后再关联查询,极大提升速度。2、分页优化器:page-optimize 让分页查询由两次变成1.3~1.5次(用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询)3、sqltoy的分页取总记录的过程不是简单的select count(1) from (原始sql);而是智能判断是否变成:select count(1) from "from后语句", 并自动剔除最外层的order by4、sqltoy支持并行查询:parallel="true",同时查询总记录数和单页数据,大幅提升性能5、在极特殊情况下sqltoy分页考虑是最优化的,如:with t1 as (),t2 as @fast(select * from table1) select * from xxx 这种复杂查询的分页的处理,sqltoy的count查询会是:with t1 as () select count(1) from table1, 如果是:with t1 as @fast(select * from table1) select * from t1 ,count sql 就是:select count(1) from table12.5.2 分页sql示例  	 	 	 	 	 		 	 	 	 	 2.5.3 分页java代码调用/**  *  基于对象传参数模式  */ public void findPageByEntity() { 	StaffInfoVO staffVO = new StaffInfoVO(); 	// 作为查询条件传参数 	staffVO.setStaffName("陈"); 	// 使用了分页优化器 	// 第一次调用:执行count 和 取记录两次查询         // 第二次调用:在特定时效范围内count将从缓存获取,只会执行取单页记录查询 	Page result = sqlToyLazyDao.findPageBySql(new Page(), "sqltoy_fastPage", staffVO); } 2.6 极为巧妙的缓存翻译,将多表关联查询尽量变成单表1、 通过缓存翻译: 将代码转化为名称,避免关联查询,极大简化sql并提升查询效率2、 通过缓存名称模糊匹配: 获取精准的编码作为条件,避免关联like 模糊查询//支持对象属性注解模式进行缓存翻译 @Translate(cacheName = "dictKeyName", cacheType = "DEVICE_TYPE", keyField = "deviceType") private String deviceTypeName;  @Translate(cacheName = "staffIdName", keyField = "staffId") private String staffName; 	 	 	 	 	 		 		 	 	 	 	 2.7 并行查询接口规范// parallQuery 面向查询(不要用于事务操作过程中),sqltoy提供强大的方法,但是否恰当使用需要使用者做合理的判断 /**   * @TODO 并行查询并返回一维List,有几个查询List中就包含几个结果对象,paramNames和paramValues是全部sql的条件参数的合集   * @param parallQueryList   * @param paramNames   * @param paramValues   */ public  List> parallQuery(List parallQueryList, String[] paramNames, 			Object[] paramValues);使用范例//定义参数 String[] paramNames = new String[] { "userId", "defaultRoles", "deployId", "authObjType" }; Object[] paramValues = new Object[] { userId, defaultRoles, GlobalConstants.DEPLOY_ID, 		SagacityConstants.TempAuthObjType.GROUP }; // 使用并行查询同时执行2个sql,条件参数是2个查询的合集 List> list = super.parallQuery( 		Arrays.asList( 		        ParallQuery.create().sql("webframe_searchAllModuleMenus").resultType(TreeModel.class), 				ParallQuery.create().sql("webframe_searchAllUserReports").resultType(TreeModel.class)), 		paramNames, paramValues); 		2.8 跨数据库支持1、提供类似hibernate性质的对象操作,自动生成相应数据库的方言。2、提供了常用的:分页、取top、取随机记录等查询,避免了各自不同数据库不同的写法。3、提供了树形结构表的标准钻取查询方式,代替以往的递归查询,一种方式适配所有数据库。4、sqltoy提供了大量基于算法的辅助实现,较大程度上用算法代替了以往的sql,实现了跨数据库5、sqltoy提供了函数替换功能,比如可以让oracle的语句在mysql或sqlserver上执行(sql加载时将函数替换成了mysql的函数),较大程度上实现了代码的产品化。 default:SubStrTrimInstrConcatNvl 函数;可以参见org.sagacity.sqltoy.plugins.function.Nvl 代码实现           6、通过sqlId+dialect模式,可针对特定数据库写sql,sqltoy根据数据库类型获取实际执行sql,顺序为: dialect_sqlId->sqlId_dialect->sqlId, 如数据库为mysql,调用sqlId:sqltoy_showcase,则实际执行:sqltoy_showcase_mysql	 		 			 		 	          	 		 			 		 	2.9 提供行列转换、分组汇总、同比环比等水果销售记录表
  品类
  销售月份
  销售笔数
  销售数量(吨)
  销售金额(万元)
  苹果
  2019年5月
  12
  2000
  2400
  苹果   2019年4月   11
  1900
  2600
  苹果   2019年3月   13
  2000
  2500
  香蕉   2019年5月   10
  2000
  2000
  香蕉   2019年4月   12
  2400
  2700
  香蕉   2019年3月   13
  2300
  2700 2.9.1 行转列(列转行也支持) 效果   品类   2019年3月   2019年4月   2019年5月   笔数   数量   总金额   笔数   数量   总金额   笔数   数量   总金额   香蕉   13
  2300
  2700
  12
  2400
  2700
  10
  2000
  2000
  苹果   13
  2000
  2500
  11
  1900
  2600
  12
  2000
  2400 2.9.2 分组汇总、求平均(可任意层级) 效果   品类   销售月份   销售笔数   销售数量(吨)   销售金额(万元)   总计   71
  12600
  14900
  小计   36
  5900
  7500
  苹果   2019年5月   12
  2000
  2400
  苹果   2019年4月   11
  1900
  2600
  苹果   2019年3月   13
  2000
  2500
  小计   35
  6700
  7400
  香蕉   2019年5月   10
  2000
  2000
  香蕉   2019年4月   12
  2400
  2700
  香蕉   2019年3月   13
  2300
  27002.9.3 先行转列再环比计算 效果   品类   2019年3月   2019年4月   2019年5月   笔数   数量   比上月   总金额   比上月   笔数   数量   比上月   总金额   比上月   笔数   数量   比上月   总金额   比上月   香蕉   13
  2300
  2700
  12
  2400
  4.30%   2700
  0.00%   10
  2000
  -16.70%   2000
  -26.00%   苹果   13
  2000
  2500
  11
  1900
  -5.10%   2600
  4.00%   12
  2000
  5.20%   2400
  -7.70% 2.10 分库分表2.10.1 查询分库分表(分库和分表策略可以同时使用) sql参见quickstart项目:com/sqltoy/quickstart/sqltoy-quickstart.sql.xml 文件 =:beginDate] #[and t.log_date<=:endDate] ]]> =:beginDate #[and t.trans_date<=:endDate] ]]> 2.10.2 操作分库分表(vo对象由quickvo工具自动根据数据库生成,且自定义的注解不会被覆盖)   @Sharding 在对象上通过注解来实现分库分表的策略配置   参见:com.sqltoy.quickstart.ShardingSearchTest 进行演示package com.sqltoy.showcase.vo; import java.time.LocalDate; import java.time.LocalDateTime; import org.sagacity.sqltoy.config.annotation.Sharding; import org.sagacity.sqltoy.config.annotation.SqlToyEntity; import org.sagacity.sqltoy.config.annotation.Strategy; import com.sagframe.sqltoy.showcase.vo.base.AbstractUserLogVO; /* * db则是分库策略配置,table 则是分表策略配置,可以同时配置也可以独立配置 * 策略name要跟spring中的bean定义name一致,fields表示要以对象的哪几个字段值作为判断依据,可以一个或多个字段 * maxConcurrents:可选配置,表示最大并行数 maxWaitSeconds:可选配置,表示最大等待秒数 */ @Sharding(db = @Strategy(name = "hashBalanceDBSharding", fields = { "userId" }), // table = @Strategy(name = "hashBalanceSharding", fields = {"userId" }), maxConcurrents = 10, maxWaitSeconds = 1800) @SqlToyEntity public class UserLogVO extends AbstractUserLogVO { private static final long serialVersionUID = 1296922598783858512L; /** default constructor */ public UserLogVO() { super(); } } 2.11 五种非数据库相关主键生成策略(可自扩展)主键策略除了数据库自带的 sequenceidentity 外包含以下数据库无关的主键策略。通过quickvo配置,自动生成在VO对象中。2.11.1 shortNanoTime 22位有序安全ID,格式: 13位当前毫秒+6位纳秒+3位主机ID2.11.2 nanoTimeId 26位有序安全ID,格式:15位:yyMMddHHmmssSSS+6位纳秒+2位(线程Id+随机数)+3位主机ID2.11.3 uuid:32 位uuid2.11.4 SnowflakeId 雪花算法ID2.11.5 redisId 基于redis 来产生规则的ID主键   根据对象属性值,产生规则有序的ID,比如:订单类型为采购:P 销售:S,贸易类型:I内贸;O 外贸; 订单号生成规则为:1位订单类型+1位贸易类型+yyMMdd+3位流水(超过3位自动扩展) 最终会生成单号为:SI1911200012.12 elastic原生查询支持2.13 elasticsearch-sql 插件模式sql模式支持2.14 sql文件变更自动重载,方便开发和调试2.15 公共字段统一赋值,针对创建人、创建时间、修改人、修改时间等2.16 提供了查询结果日期、数字格式化、安全脱敏处理,让复杂的事情变得简单3.集成说明3.1 参见trunk 下面的quickstart,并阅读readme.md进行上手package com.sqltoy.quickstart; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * * @project sqltoy-quickstart * @description quickstart 主程序入口 * @author zhongxuchen * @version v1.0, Date:2020年7月17日 * @modify 2020年7月17日,修改说明 */ @SpringBootApplication @ComponentScan(basePackages = { "com.sqltoy.config", "com.sqltoy.quickstart" }) @EnableTransactionManagement public class SqlToyApplication { /** * @param args */ public static void main(String[] args) { SpringApplication.run(SqlToyApplication.class, args); } } 3.2 application.properties sqltoy部分配置# sqltoy config spring.sqltoy.sqlResourcesDir=classpath:com/sqltoy/quickstart spring.sqltoy.translateConfig=classpath:sqltoy-translate.xml spring.sqltoy.debug=true #spring.sqltoy.reservedWords=status,sex_type #dataSourceSelector: org.sagacity.sqltoy.plugins.datasource.impl.DefaultDataSourceSelector #spring.sqltoy.defaultDataSource=dataSource # 提供统一公共字段赋值(源码参见quickstart) spring.sqltoy.unifyFieldsHandler=com.sqltoy.plugins.SqlToyUnifyFieldsHandler #spring.sqltoy.printSqlTimeoutMillis=200000 3.3 缓存翻译的配置文件sqltoy-translate.xml<?xml version="1.0" encoding="UTF-8"?> =:lastUpdateTime ]]> =:lastUpdateTime ]]> =:lastUpdateTime ]]> 实际业务开发使用,直接利用SqlToyCRUDService 就可以进行常规的操作,避免简单的对象操作自己写service, 另外针对复杂逻辑则自己写service直接通过调用sqltoy提供的:SqlToyLazyDao 完成数据库交互操作!@RunWith(SpringRunner.class) @SpringBootTest(classes = SqlToyApplication.class) public class CrudCaseServiceTest { @Autowired private SqlToyCRUDService sqlToyCRUDService; /** * 创建一条员工记录 */ @Test public void saveStaffInfo() { StaffInfoVO staffInfo = new StaffInfoVO(); staffInfo.setStaffId("S190715005"); staffInfo.setStaffCode("S190715005"); staffInfo.setStaffName("测试员工4"); staffInfo.setSexType("M"); staffInfo.setEmail("test3@aliyun.com"); staffInfo.setEntryDate(LocalDate.now()); staffInfo.setStatus(1); staffInfo.setOrganId("C0001"); staffInfo.setPhoto(FileUtil.readAsBytes("classpath:/mock/staff_photo.jpg")); staffInfo.setCountry("86"); sqlToyCRUDService.save(staffInfo); } }4. sqltoy sql关键说明4.1 sqltoy sql最简单规则#[] 对称符号#[] 等于if(中间语句参数是否有null)? true: 剔除#[] 整块代码,false:拿掉#[ 和 ] ,将中间的sql作为执行的一部分。#[] 支持嵌套,如#[t.status=:status #[and t.createDate>=:createDate]] 会先从内而外执行if(null)逻辑利用filters条件值预处理实现判断null的统一,下面是sqltoy完整提供的条件过滤器和其他函数 不要被大段的说明吓一跳,99%都用不上,正常filters里面只会用到eq 和 to-date :beginDate] #[and t.STAFF_NAME like :staffName] -- 是否虚拟员工@if()做逻辑判断 #[@if(:isVirtual==true||:isVirtual==0) and t.IS_VIRTUAL=1] ) t1,sys_organ_info t2 where t1.ORGAN_ID=t2.ORGAN_ID ]]> 5. sqltoy关键代码说明5.1 sqltoy-orm 主要分以下几个部分:SqlToyDaoSupport:提供给开发者Dao继承的基本Dao,集成了所有对数据库操作的方法。SqlToyLazyDao:提供给开发者快捷使用的Dao,让开发者只关注写Service业务逻辑代码,在service中直接调用lazyDaoSqltoyCRUDService:简单Service的封装,面向controller层提供基于对象的快捷service调用,比如save(pojo)这种极为简单的就无需再写service代码DialectFactory:数据库方言工厂类,sqltoy根据当前连接的方言调用不同数据库的实现封装。SqlToyContext:sqltoy上下文配置,是整个框架的核心配置和交换区,spring配置主要是配置sqltoyContext。EntityManager:封装于SqlToyContext,用于托管POJO对象,建立对象跟数据库表的关系。sqltoy通过SqlToyEntity注解扫描加载对象。ScriptLoader:sql配置文件加载解析器,封装于SqlToyContext中。sql文件严格按照*.sql.xml规则命名。TranslateManager:缓存翻译管理器,用于加载缓存翻译的xml配置文件和缓存实现类,sqltoy提供了接口并提供了默认基于ehcache的本地缓存实现,这样效率是最高的,而redis这种分布式缓存IO开销太大,缓存翻译是一个高频度的调用,一般会缓存注入员工、机构、数据字典、产品品类、地区等相对变化不频繁的稳定数据。ShardingStragety:分库分表策略管理器,4.x版本之后策略管理器并不需要显式定义,只有通过spring定义,sqltoy会在使用时动态管理。5.2 快速阅读理解sqltoy:从SqlToyLazyDao作为入口,了解sqltoy提供的所有功能SqlToyDaoSupport 是SqlToyLazyDao 具体功能实现。从DialectFactory会进入不同数据库方言的实现入口。可以跟踪看到具体数据库的实现逻辑。你会看到oracle、mysql等分页、取随机记录、快速分页的封装等。EntityManager:你会找到如何扫描POJO并构造成模型,知道通过POJO操作数据库实质会变成相应的sql进行交互。ParallelUtils:对象分库分表并行执行器,通过这个类你会看到分库分表批量操作时如何将集合分组到不同的库不同的表并进行并行调度的。SqlToyContext:sqltoy配置的上下文,通过这个类可以看到sqltoy全貌。PageOptimizeUtils:可以看到分页优化默认实现原理。六、源码地址   访问一飞开源:https://code.exmay.com/

哈登怒推大帝!揭幕战双核就公然冲突76人却该因此感到欣慰北京时间10月19日,NBA常规赛正式开启,在赛季揭幕战中,76人客场挑战凯尔特人,结果第一节场上就风波不断,除了艾尔霍福德垫脚哈登被吹恶意犯规外,76人队的两位超级球星之间也疑似上海男篮33分惨败浙江,李春江不但输给了自己,还输给丁彦雨航李春江的豪华上海男篮却以33分的大比分输给浙江男篮,这是人们都出乎预料和意想不到的一场比赛,那么,李春江到底输在了哪里?球迷认为李春江不但输给了自己!李春江还输给了丁彦雨航!立体看NBA揭幕战2场比赛,分析一下各球员表现北京时间10月19日,NBA20222023赛季揭幕战打响,2场比赛结果分别是76人117凯尔特人126,湖人109勇士123。凯尔特人和勇士均取得开门红。一首先看看76人和凯尔特包教包会!全网最全领带系法汇总如果说身上只能用一件东西来通过搭配来展现出不同穿着风格,不同的心情那么就一定是领带了领带作为最重要的西装配饰之一,领带打法也大有文章哦!除了最常见的温莎结,今天再给大家分享8个领带谁说美女只能白幼瘦!菲律宾大码辣妹告诉你什么叫丰满美白幼瘦,顾名思义,白皮肤幼龄态瘦身材。这种标准化的审美不仅影响着广大中国女性,连中国周边的日本韩国女性,也一样在追逐这种美女标准。但是今天,我们要讲的是另一种美女,脱离白幼瘦的固化包教包会!全网最全领带系法汇总如果说身上只能用一件东西来通过搭配来展现出不同穿着风格,不同的心情那么就一定是领带了领带作为最重要的西装配饰之一,领带打法也大有文章哦!除了最常见的温莎结,今天再给大家分享8个领带谁说美女只能白幼瘦!菲律宾大码辣妹告诉你什么叫丰满美白幼瘦,顾名思义,白皮肤幼龄态瘦身材。这种标准化的审美不仅影响着广大中国女性,连中国周边的日本韩国女性,也一样在追逐这种美女标准。但是今天,我们要讲的是另一种美女,脱离白幼瘦的固化凭借反派角色展现魅力的九头身美女菜菜绪身为高个子唯一的烦恼,大概是在拍古装剧会显得突兀。因此跪坐的时候,她会尽量压低身体,使自己看起来变得娇小。在2021年冬季档日剧哦!我的老板!恋爱随书附赠当中,饰演时尚杂志总编辑的清纯与魅惑并存,女神吴宣仪性感写真曝光吴宣仪内地流行音乐女歌手演员,凭借超高的颜值动人的歌喉曼妙的舞姿,号称综艺之王,流量女王。我们今天就来欣赏下女神吴宣仪的高清写真照。第一组吴宣仪身穿黑色高开叉长裙,优雅高贵,裙尾曳4战3败!CBA土豪队又输了,豪华阵容变笑话,七冠教头脸色铁青北京时间10月19日,CBA常规赛继续进行,上海男篮对阵天津男篮,上海首节挖下13分大坑,不过半场就反超了6分。下半场,两队依旧紧咬比分,上海在末节落后10分的情况下一度反超,不过队报博格巴将在11月初复出,他想适应比赛以便参加世界杯据法国媒体队报的报道,在接受右膝手术仅一个月后,法国中场保罗博格巴已经恢复了尤文的小组训练,他将寻求在11月初重返赛场。而目前,距离卡塔尔世界杯开始还有一个多月的时间。据此前媒体的
苏州真香!又一个千亿级产业加速崛起俗话说,民以食为天不过你知道吗你平日上班时吃的面包加班时点的咖啡很可能是苏州产的食品产业是为耕者谋利为食者造福的重要民生产业近年来知名企业纷纷加码布局苏州高端食品产业聚势而强一个千2023上海车展文远知行张冬冬高阶智能驾驶产品今年量产落地出品搜狐汽车汽车咖啡馆编者按2023年4月18日,以拥抱汽车行业新时代为主题的2023第二十届上海国际汽车工业展览会在沪举办。2023上海车展作为今年全球第一场A级车展备受全球汽车广交会万商云集,参会外商怎么说?作者丨施诗,李依农,实习生王斯琦编辑丨和佳,剪辑李群广交会开放魅力不减,万商云集盛况再现。本届广交会,超过220个国家和地区的采购商报名近50家工商机构将组团参会,其中不乏超过20昌平永旺梦乐城6月撤店外资企业如何站稳北京市场日企永旺在北京市场的版图正不断缩小。4月19日,北京商报记者走访位于永旺集团旗下的昌平梦乐城发现,该商场电梯停运门店围挡,商户打折促销。相关人士透露,昌平梦乐城将于6月24日全面关我们更应看到深藏SpaceX星舰计划背后的真相SpaceX计划于2023年4月17日(北京时间周一晚上8点)进行星舰的首次轨道飞行测试,但由于压力阀冻结导致发射推迟。这是该公司首次尝试将星舰送入轨道,如果成功,这将是马斯克将人苹果又要放弃老机型,iOS17将不支持3GB内存设备,你的老手机会被淘汰吗?WWDC即将在6月召开,苹果将正式公布iOSiPadOS17系统,目前有关iOS17的设计细节已经被大量曝光。新系统将会带来一些重要的变化,例如控制中心和搜索体验会有大幅改进,同时太卷了!2023五一,2K档手机也可一次到位,至少流畅用四年如果您喜欢,可以点击上面的关注二字。后续会为您提供更多有价值的内容。每天分享太卷了!2023五一,2K档手机也可一次到位,至少流畅用四年。第一款vivoiQOONeo7竞速版参考价同方超越E500新品抢先看13代酷睿震撼来袭说到商用台式机,同方或许是大部分行业用户能想到的主力品牌,能受到市场广泛认可,自然与同方优秀的产品设计以及硬核用料分不开。凭此优势,清华同方再度携手英特尔,带来新款超越E500台式75英寸智能电视跌至两千档,为何仍卖不出?网友广告和付费太坑随着手机电脑等数码产品的普及,人们看视频的工具也不再局限于电视一种。也正因如此,电视这一产品也遭遇危机,近几年来整体销量呈现逐渐下降趋势,即使大屏电视需求增加,也挽救不了整体的颓势年轻人的家到底有多舒服,按摩椅放家里一台,实在是太享受年轻人的家到底有多舒服?现在年轻人装的房子到底有多舒服?回家不用带钥匙开门灯光自动亮起,扫地拖地交给机器人,吃完饭刷碗交给洗碗机,上厕所马桶盖还可以自动打开。早上7点窗帘可以自动打12款儿童手表测试!华为长虹读书郞普耐尔等样品表现不佳近日河北省石家庄市消保委发布儿童智能手表样品比较试验分析报告12款样品品牌涉及长虹华为读书郎小天才清华同方360等款上下滑动,查看样品详情试验结果12款样品在应用程序自身防护机制方