`
Tristan_S
  • 浏览: 378102 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

----2016----

    博客分类:
  • LJ
 
阅读更多
---------------------------------------------
springBoot 的jdbc连接池
默认使用tomcat的连接池
JdbcTemplate.dataSource.poolProperties 中有一切,甚至是密码
默认的maxActive 是100 

由于网络的一些问题(vpn),会造成连接池的不可用
com.microsoft.sqlserver.jdbc.SQLServerException: 该连接已关闭。
这几个参数能保证及时网络有问题, 连接池也是可用的
testWhileIdle=true
testOnBorrow=true
validationQuery=select 1
removeAbandoned=true


--------------------------------------
tomcat的maxThread 500限制测试
http://blog.csdn.net/jackpk/article/details/32137483


----------------------------------------------
如何查看系统的并发数(某段时间)
accessLog ?
接口项目是可以通过accessLog来计算, web项目则不行, 会有很多的resource文件加载
web项目可以用这种方式
grep -v ".js\|.css\|.html\|.png" access_log.2016-08-22.log


http://www.xuebuyuan.com/661140.html   --参数详情
http://www.cnblogs.com/huligong1234/p/4220017.html   --增加配置  Tomcat通过%D或%T统计请求响应时间


AppServer的
cat access_log.2016-08-21.log  |wc -l 
--> 519310 = 每秒6个请求
grep -v "queryRollingMessage" access_log.2016-08-21.log  |wc -l
--> 91812 排除了微聊轮播后的数据

PNS的
每天1454636  = 17个/秒
高峰7850/分钟 = 130个/秒 通过awk来计算
参考 http://huoding.com/2013/01/26/215


使用awk来分析accessLog 的访问量分布情况
awk -F: '{count[$2":"$3]++}END {for (minute in count) print minute, count[minute]}' localhost_access_log.2016-08-21.txt | sort > count.log
awk -F: '{count[$2]++}END {for (hour in count) print hour, count[hour]}' access_log.2016-08-22.log | sort > count2.log

sort -n -r -k 2  count.log

SpringBoot
server.tomcat.max-threads=2000 默认
server.tomcat.accesslog.enabled=true  可以 默认为false
server.tomcat.access-log-enabled=true  没有效果
server.tomcat.basedir=/home/log/${spring.application.name}
还有线程delay的
server.tomcat.background-processor-delay=30


-------------------------------------------------------
秒杀系统  --业务上是个性价比很低的系统

---锁
java的synchronized 针对的是一个JVM, 而对于集群环境没啥用, 只能用集中式缓存和DB中控制

---纯技术上
1, CDN
2, nginx 拒绝请求
3, cache
4, 乐观锁
5, queue 异步回复结果或是比较长的时间

---业务上
1, 验证码 --防止机器人
2, 黄牛账号分析

---负载量
吞吐量QPS(Query) 
一个业务请求平均响应时间100ms
集群中有10tomcat 每台的maxThread是500个
QPS = 10*500/0.1 = 5w(QPS)

--其他
独立部署,以防对现有网站的冲击
秒杀商品页面静态化+cdn
租借阿里云
CDN nginx tomat db  数据量层层减少



---------------------------------------------------
spring的RestTemplate使用
getForObject   postForObject  是 exchange的简化版, 没有Header
以前公司用的是easyrest
		RestTemplate rt = new RestTemplate();
//		String url = "http://pns.dooioo.com/message/scrollListRich/165641/1009";
//		String forObject = rt.getForObject(url, String.class);
//		System.out.println(forObject);

HttpEntity entity = new HttpEntity<String>(body);
		ResponseEntity<JSONObject> exchange = rt.exchange(url, HttpMethod.POST, entity , JSONObject.class);
		System.out.println(exchange.getBody());




---------------------------------------------------
利用Guava的Joiner, 将List转换为逗号分隔符

List<String> list = new ArrayList<String>();  
list.add("a");  
list.add("b");  
list.add("c");  
String str = Joiner.on(",").join(list);  



--------------------------------------------
tomcat在catalina.sh中修改内存参数, 有时会被setenv.sh中的参数覆盖


--------------------------------------------
stream()有点用处的地方

userCodeSet = subOrgList.stream().map(Employee::getUserCode).collect(Collectors.toSet());
/*for (Employee employee : subOrgList) {
	userCodeSet.add(employee.getUserCode());
}*/




--------------------------------------------
琪琪学习
1, 上传控件问题
   a> 控件中缺少一个参数,  在console中可以看到error
   b> 成功时没有callback, 搜索successCallback关键字 返回的对象需要被解析成json,否则报错,catch后没有处理
   c> 后端接受文件时用 @RequestParam("fileObject") MultipartFile file  需要修改文件名

2, 其他
   a> 当页面编码为GBK时, 会影响到后面加载JS的编码, 导致加载失败 用$.getScript()可以检验是否加载js成功
   b> $.ajax 中的dataType:"json" 是用来表明返回对象的类型, contentType: "application/json; charset=GBK", 是用来表示request的类型

3, 页面
  a> <pre>可以用来显示出db中文本自带的换行符,
    style="white-space: pre-line;" 用于过长的文本的换行
  b> 图片没有显示全 用 background-size: contain;
     字和图片挤在一起用  padding-left: 25px;
  c> header加载不出来 是由于js css div之间的顺序关系,  js自己也有顺序关系



--------------------------------------------
sql 列转行
http://www.cnblogs.com/maanshancss/archive/2013/03/13/2957108.html

SELECT id,
 MAX(CASE type WHEN 1 THEN countUserData ELSE 0 END) as '1',
 MAX(CASE type WHEN 2 THEN countUserData ELSE 0 END) as '2',
 MAX(CASE type WHEN 3 THEN countUserData ELSE 0 END) as '3'
FROM tt
GROUP BY id;


公司
SELECT x.backgroundId,
 MAX(CASE type WHEN 1 THEN countUserData ELSE 0 END) as userDataType1,
 MAX(CASE type WHEN 2 THEN countUserData ELSE 0 END) as userDataType2,
 MAX(CASE type WHEN 3 THEN countUserData ELSE 0 END) as userDataType3
 FROM (select t2.backgroundId, t2.type , count(t2.backgroundId) as countUserData
                from t_background_user_data  t2 with(nolock)
                group by t2.backgroundId , t2.type) x
 GROUP BY x.backgroundId


可以改写成  不用MAX
这个就是典型的行转列的用法, case when 的升级版
           select t2.backgroundId
         ,COUNT(CASE type WHEN 1 THEN backgroundId END) as userDataType1
         ,COUNT(CASE type WHEN 2 THEN backgroundId END) as userDataType2
         ,COUNT(CASE type WHEN 3 THEN backgroundId END) as userDataType3
         from t_background_user_data  t2 with(nolock)
         group by t2.backgroundId



行转列 核心就是用的聚合函数
数字的值是可以用 count, 但是string则不行, 需要用for xml的方式

select t.userCode,t.conversationId, 
(
		select t2.customerId + ',' from t_mircoChat_complain t2
		where t2.userCode = t.userCode and t2.conversationId = t.conversationId
		FOR XML PATH('')
    ) as ids
 from dbo.t_mircoChat_complain t --where t.userCode =83074 and t.conversationId = '56e2c0d42627f372f8d00fa1'
group by t.userCode, t.conversationId;


还可以在java端用一次主查询加上n次子查询来做

--------------------------------------------
DNS也可以做负载均衡 但是需要很好的网络背景知识
dig 命令可以查询dns解析的地址, 属于系统管理员范围
dig www.baidu.com +short

www.a.shifen.com.
115.239.211.112
115.239.210.27


dig www.baidu.com +trace

http://www.2cto.com/os/201408/325875.html

--------------------------------------------
varchar 和 nvarchar的区别
一般如果用到中文或者其它特殊字符,我就会使用n开头的类型,否则的话直接使用var开头的。

nvarchar 字节的存储大小是所输入字符个数的两倍

varchar(50)  可以存放50个英文.  50个中文会报错
nvarchar(50)  可以存放50个中文.



--------------------------------------------
lambda 实现匿名内部类

 String query = "SELECT first_name, last_name, age" +
                " from person where person.id = " + id;
       
        RowMapper<Person> rowMapper = new RowMapper<Person>() {
			@Override
			public Person mapRow(ResultSet rs, int rowNum) throws SQLException {
				return new Person(rs.getString(1), rs.getString(2), rs.getInt(3));
			}
		};
		return jdbcTemplate.queryForObject(query, rowMapper);
		
       /* return jdbcTemplate.queryForObject(query, (resultSet, i) -> {
            return new Person(resultSet.getString(1), resultSet.getString(2), resultSet.getInt(3));
        });*/



--------------------------------------------
main vs JUnit
main在使用到一些spring.xml或是memcache等系统资源时无法结束,
需要手动System.exit(0)来结束,  而Junit则没这个问题


--------------------------------------------
memcache

set可以新增或是更新  add只能新增(一般不用)
gets 多返回了一个casId, 用来进行cas操作, 如果casId不同的话, 可以用while循环加sleep个10ms来轮询
boolean writelock = true;
        int retNum = 100;
        while (writelock && retNum-- > 0){
            writelock = false;
            try {
                GetsResponse<Set<String>> getsResponse = fyMemcachedClient.gets(empNo.toString(),1000);
                if(getsResponse == null || getsResponse.getValue() == null){

                }else{
                    Set<String> set = getsResponse.getValue();
                    set.remove(propertyId+","+session.getId());
                    if (!fyMemcachedClient.cas(empNo.toString(), 3600*12, set, getsResponse.getCas())) {
                        writelock = true;
                        Thread.sleep(10);
                    }
                }
            } catch (TimeoutException | InterruptedException | MemcachedException e) {
                e.printStackTrace();
            }

        }


--------------------------------------------
springMVC 静态资源配置
http://www.cnblogs.com/yank/p/4477204.html

---------------------------------------------
SQL Server 中id递增的 不能手动指定, 需要重新设置index
DBCC checkident(T_Business_Side,reseed,1018);

更好的办法是
SET IDENTITY_INSERT dbo.xxx ON
  GO

直接指定id, 之后需要OFF掉
--------------------------------------
soapUI 中的Header添加
Content-Type  text/html; charset=GBK
可以解决
1, 请求被fastjson拦截
2, 报文体不支持中文


--------------------------------------
CPU 50%  4核机器
	private static void cpu50() throws InterruptedException {
		new Thread(() -> {
			long l = 0;
			while (true) {
				l++;
			}
		}).start();
		
		new Thread(() -> {
			long l2 = 0;
			while (true) {
				l2++;
			}
		}).start();
		
		Thread.sleep(Long.MAX_VALUE);
	}



--------------------------------------
CPU 100%问题  top --> jstack
http://www.tuicool.com/articles/AbeeQz
http://bbs.csdn.net/topics/390666435


---------------------------------------
linux发送邮件
http://blog.sina.com.cn/s/blog_48ab118d0101fo3q.html
http://www.linuxidc.com/Linux/2014-10/107946.htm

--------------------------------------
微服务研究下   
【Feign】 RPC  
【Eureka】 服务发现(仪表盘) 
【Configuration】 git  
【查看关联了几个service】  http://ms.dooioo.org/admin/health

---------------------------------------
用(String) 强转碰到null也不会出问题, 比toString() 更安全

Object obj = null;
System.out.println((String)obj);
System.out.println(obj.toString());



--------------------------------------------
微服务存在的问题
1>  Controller中的异常被外部框架捕获了, 无法打印出堆栈信息
2>  历史价格会调用后台 20(页)*3(其他接口)+1 = 61次接口请求,  速度慢.
而且由于是分页查询,无法做缓存


--------------------------------------------
接口返回list,需要转换成标准的json
Object json = JSON.toJSON(list)



--------------------------------------------
sqlserver 的分页太烂了
http://blog.csdn.net/qiaqia609/article/details/41445233

推荐的代码是
定位法 (利用ID大于多少)

语句形式:

select top 10 * from tbl_FlightsDetail where FlightsDetailID>(
       select max(FlightsDetailID) from ( 
              select top 3000000 FlightsDetailID from tbl_FlightsDetail order by FlightsDetailID
       ) as t
) order by FlightsDetailID

--------------------------------------------
row_number 的使用







--------------------------------------------
ArrayList 没有concurrent版本, hashMap的concurrent版是基于分桶的.

LinkedHashSet 可以按照插入顺序排序

--------------------------------------------
maven冲突
commons-lang-2.6 和commons-lang-3.7 很容易出现冲突(有些jar包底层依赖于2.6), 编译的时候能通过, 打包的时候无法解析StringUtils
在 Dependency Hierarchy中将2.6版本间接加载的内容去掉, 将项目代码中的StringUtils改成3.7, 再将2.6的内容加回去


--------------------------------------------
select * from 视图  很可能由于查询的数据太多导致吃不到索引, 走全表扫描
PNS v_message_history 中去掉readTime和status字段.(某些用户有大量消息的时候发生)

第一次查询慢 第二次快的现象
可能是第一次全表扫,需要读磁盘,把数据加到内存里。间隔很短的第二次应该就直接内存了
过一段时间,内存的数据没有访问会被刷走,再来访问,就要重新走磁盘



--------------------------------------------
线上发布应用是最好用kill 不加-9 [就是-15]来停, 这样能保证所有当前正在运行的线程能顺利结束
如果实在停不了的话再用 kill -9


--------------------------------------------
删除1234月份的日志
info2016[1234].log

--------------------------------------------
log4j日志保留天数
DailyRollingFileAppender 不支持最大日志数量
http://blog.sina.com.cn/s/blog_6f505d710101bq1e.html

--------------------------------------
起线程异步调用
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
		singleThreadExecutor.execute(() -> behaviorLogService.insertLoginLog(behaviorLog));
		
		//new Thread(() -> behaviorLogService.insertLoginLog(behaviorLog));



--------------------------------------
maven-shade-plugin 取代 maven-assembly-plugin
assembly 在打spring包时有问题 
http://chenzhou123520.iteye.com/blog/1706242
在META-INF下会有多余的以SF结尾的文件,删除后不会出现次问题

--------------------------------------
数据库设计 -- free style
高并发 走cache
复杂查询 走solr
灵活性 走json / mongodb
海量数据查询 走hbase rowkey


-----------------------------------
查看linux 的ip
用InetAddress.getLocalHost().getHostAddress(); 的方式只能看到127.0.0.1
javac -d . TristanAsync.java
java com/dooioo/microChartTool/asc/TristanAsync

 public static InetAddress getLocalHost() {
	        Enumeration<NetworkInterface> netInterfaces = null;
	        try {
	            netInterfaces = NetworkInterface.getNetworkInterfaces();
	            while (netInterfaces.hasMoreElements()) {
	                NetworkInterface ni = netInterfaces.nextElement();
	                Enumeration<InetAddress> ips = ni.getInetAddresses();
	                while (ips.hasMoreElements()) {
	                    InetAddress ip = ips.nextElement();
	                    if (ip.isSiteLocalAddress()) {
	                        return ip;
	                    }
	                }
	            }
	        } catch (Exception e) {
	        	System.out.println(e.getMessage());
	        }
	        return null;
	    }








-----------------------------------
springMVC 学习
1, 创建maven项目, 选择webapp的archetype
2, JSP中用${error}来获取model中的值
3, 在web.xml中用DispatcherServlet来取代原来的ContextLoaderListener
4, DispatcherServlet 对应的xml中,只需要一个<context:component-scan/> 就ok
5, 拦截器 loginInterceptor 某些路径不需要拦截(/api,/static等). [房源]
6, 异常处理 @ExceptionHandler BaseController
7, 视图解析器
return "/WEB-INF/jsp/"+pageName+".jsp"  变成了  return pageName;

8, <!-- 支持异步方法 / 支持定时任务-->
    <task:annotation-driven/>



-----------------------------------
grep匹配符 .*
grep "V4.*scrollList duration" info.log|less

--------------------------------
按日统计  按月统计
select CONVERT(varchar(10), t.createTime, 23) as createDate, count(1)
from t_message t with(nolock)
where t.createTime > '2016-05-01'
group by CONVERT(varchar(10), t.createTime, 23)
order by CONVERT(varchar(10), t.createTime, 23) asc;

select CONVERT(char(7), t.createTime, 23) as createDate, count(1)
from t_message t with(nolock)
where t.createTime > '2016-01-01'
group by CONVERT(char(7), t.createTime, 23)
order by CONVERT(char(7), t.createTime, 23) asc;

select getdate();

SELECT CONVERT(varchar(100),getdate(),23) now;

【历史表一起统计】
select CONVERT(char(7), t.createTime, 23) as createDate, count(1)
from dbo.T_Message_Read t with(nolock)
where t.createTime > '2016-01-01'
group by CONVERT(char(7), t.createTime, 23)
--order by CONVERT(char(7), t.createTime, 23) asc
UNION all
select CONVERT(char(7), t.createTime, 23) as createDate, count(1)
from dbo.T_Message_Read_History t with(nolock)
where t.createTime > '2016-01-01'
group by CONVERT(char(7), t.createTime, 23)
order by CONVERT(char(7), t.createTime, 23) asc;
-----------------------------
短信供应商延迟的问题, 可以在短信文本中写上日期, 这样就能确定是我们的问题还是供应商的问题了

--------------------------------
PNS发送消息改成异步的风险

如果直接返回一个ok, 外部系统循环调用的话就会,pns这里就可能出现并发的问题.
当然如果外系统用开线程的方式并行来调的话, 这就不可避免的.
5秒钟的超时时间, 至少可以保护pns的压力.
pns后台逻辑还是很复杂的, 大量的数据库读写, leanCloud通讯, 所以出现并发问题会很麻烦, 不改了,  用blockingQueue的话会有其他方面的问题


--------------------------------

端口占用问题
netstat -anp | grep 端口
ps -aux | grep pid

--------------------------------
js
js可以通过 window.location.href 获取url中的参数
debugger 可以强行打个断点

-----------------------------------------
JDK7自动关闭的try语句
try (字节流输出输出等可能异常的语句)
{ }
catch (Exception e) {
e.printStackTrace();
}
可以不用显式关闭

-----------------------------------------
用jvisualvm (profiler - cpu) 可以看到
1> 哪些方法耗时多
2> 哪些方法调用次数多
3> 调用的顺序关系

-----------------------------------------
jar包读取外面的配置文件, 可以用这种方式, 同时支持linux和windows
	        Properties p = new Properties();  
	        InputStream in = null;
	        try{
	        	in = new FileInputStream("/home/app/microChat/microChat.properties");  
	        }catch(Exception e){
	        	log.info("use windows property");
	        	in=new FileInputStream("D:\\eclipse-jee-luna-SR2-win32-x86_64\\svn\\microChatTool\\src\\main\\resources\\microChat.properties");
	        }
            p.load(in);  
            in.close();





-----------------------------------------
assembly 打包, 将依赖的jar包打在一起
http://blog.csdn.net/czp11210/article/details/47808211

如果改了unpack属性后, 本项目的源代码就没了



---------------------------------------------------
java.sql.Date 只存储日期数据不存储时间数据
// 会丢失时间数据
preparedStatement.setDate(1, new java.sql.Date(date.getTime()));
//可以这样来处理
preparedStatement.setTimestamp(1, new java.sql.Timestamp(new java.util.Date().getTime()));



----------------------------------------------
java的URLEcnode不会对特殊字符编码

例如
原始代码
select * from _Conversation where attr.phone='18529'

URLEcnode后的. 手动将+号转成%20
select%20*%20from%20_Conversation%20where%20attr.phone%3D%2718529%27

而标准的应该的是(通过CURL -v 打印出来的)
select%20%2A%20from%20%5FConversation%20where%20attr%2Ephone%3D%2718529%27


----------------------------------------------
JSONObject  toJSONString  toJSON 区别
String jsonString = JSONObject.toJSONString(esEmployee);
可以吃到@JSONField中定义的格式
@JSONField(format="yyyy-MM-dd'T'HH:mm:ssZ")
private Date occurTime;

String jsonString = JSONObject.toJSON(esEmployee).toString();
则无法吃到, occurTime还是显示long的格式


-----------------------------------------
响应式布局
visible-xs-block


-----------------------------------
IdentityHashMap可以保存相同key值, 但是如果是数字的话一定要大于127

IdentityHashMap<Integer, Integer> imap = new IdentityHashMap<Integer, Integer>();
		
		int a = 127;  
		imap.put(a, 5);
		imap.put(a, 6);
		imap.put(a, 7);
		
		System.out.println(imap.size());



---------------------------------------
server端返回的数据都是string的, 即使声明成integer的话, 客户端也转不了.
服务端
	@Override
	public ResponseEntity<?> microChatData2(String param, String startDate,  String endDate) {
		List<Integer> list = behaviorLogService.microChatData2(param, startDate, endDate);
		return ResponseEntity.ok(list);
	}


客户端
		List<Integer> result = RestClient.exchange(url,HttpMethod.GET,List.class);

		for (Integer r : result) {
			syso;
		}




---------------------------------------
除法百分比
		System.out.println(369 / 809);
		System.out.println(369 % 809);

		double x = (369 * 1.0 / 809) * 100;
		System.out.println(x);
		java.text.DecimalFormat df = new java.text.DecimalFormat("#.##");
		System.out.println(df.format(x) +"%");



-------------------------------------
springMVC服务端如果是直接return个json对象, 用chrome或是api的方式 得到的是一个xml的对象.
需要将json对象转成string的
return ResponseEntity.ok(json.toString());


-------------------------------------------
Map 按照key倒排
String result = RestClient.exchange("http://localhost:9600/oms/v1/microChatData?param="+param,HttpMethod.GET,String.class);
		Map<String,Integer> map = (Map<String, Integer>) JSONObject.parse(result);
		TreeMap<String,Integer> treeMap = new TreeMap<String,Integer>(map);
		for (String key : treeMap.descendingKeySet()) {
			System.out.println(key +"  " + treeMap.get(key));
		}




-----------------------------------
mybatis的#,$ 区别
#是正对于string的 会在变量左右加上''
$则不会
例如userCode是integer的
要用 where t.userCode in (${userCode})
不能是 where t.userCode in (#{userCode})

参考  http://blog.csdn.net/downkang/article/details/12499197

---------------------------------
根据dao层对象查看数据库url
queryDao --> sqlSession --> exceptionTranslator --> dataSource -->url

---------------------------------------
性能监控 TOP  --最靠谱
P CPU排序
M 内存排序

查看内存  --不准的
free -m

统计  -- 内存数据看不出的
vmstat 5 5
--------------------------------------------
一批数据更新/插入时可以用 虚拟表union all + inner join + not exists 的方式来做

	<update id="batchUpdate" parameterType="map">
   	  update a set a.remark = #{remark}, a.updateTime = getDate(), readStatus = 1
        from t_message_last a
        inner join (
        		<foreach collection="userCodeSet" item="userCode" separator=" union all " open="(" close=")">
                select  #{appId} as appId, #{businessId} as businessId, #{userCode} as userCode
                </foreach> 
        ) b on a.userCode = b.userCode and a.appId = b.appId and a.businessId = b.businessId
   	</update>
   	
   <insert id="batchInsert" parameterType="map">
   	  insert into t_message_last(appId, businessId, userCode, businessName, remark, createTime, readStatus)
	   select a.*,#{businessName}, #{remark} , getDate(), 1
	   from (
		   <foreach collection="userCodeSet" item="userCode" separator=" union all " open="(" close=")">
		     select  #{appId} as appId, #{businessId} as businessId, #{userCode} as userCode
		   </foreach>
	    ) a
        where  not exists ( select 1 from t_message_last c where c.userCode =a.userCode and c.appId = #{appId} and c.businessId = #{businessId} );
   	</insert>



----------------------
secureCRT有时在session中设置的编码没有效果, 在需要堡垒机跳转的情况
需要在global中设置





-----------------------------------
rz  sz 命令可以在secureCRT中上传下载文件

--------------------------
String[] ss = {"a","b","c"};
List<String> asList = Arrays.asList(ss);
asList.remove("a");

这里会报错, Arrays.asList 出来的List没有实现remove方法.

可以用下列方式
		String[] s = {"a","b","c"};
		List<String> list2 = new LinkedList<String>();
		Collections.addAll(list2, s);
		list2.remove("a");
		System.out.println(list2.size());



-----------------------------
ArrayList 和 LinkedList
LinkedList删除的速度比ArrayList快


----------------------------------
delete 和 insert写在一起
delete from t_message_read output deleted.msId,deleted.userCode,deleted.createTime,deleted.updateTime,deleted.status
into T_Message_Read_History (msId, userCode, createTime, updateTime, status) where msId < ? 




------------------------------
left join on where
1. 对于left join,不管on后面跟什么条件,左表的数据全部查出来,因此要想过滤需把条件放到where后面
2. 对于inner join,满足on后面的条件表的数据才能查出,可以起到过滤作用。也可以把条件放到where后面。

 
select * from 
 (
 SELECT m.userCode , m.appId, m.businessId, m.businessName, m.createTime,m.readStatus,m.remark
 ,CASE WHEN d.userCode IS NULL THEN 1 ELSE 0 END AS disturb
,ROW_NUMBER() OVER(partition BY m.businessId ORDER BY m.id DESC) AS rowId

 FROM T_Message_Last m 
 left join dbo.T_Business_UnDisturb d 
 on d.bId = m.businessId and d.userCode = m.userCode where m.appId = 1000 and m.userCode = 104705
 ) c
 where   c.rowId = 1;


------------------
transient
某些不需要传给客户端的属性可以用transient来屏蔽掉

transient private String userCode;



------------------
泛型使用
public class Pagination<T> {
	private List<T> list;
}


--------------
JDK8
list.stream()
.map().collect(Collectors.toList())
.collect(Collectors.groupingBy(PropertyView::getPropertyId))
.filter
.anyMatch


------------
微服务
Spring Boot  以web方式启动一个jar包. 和内嵌的jetty差不多
Spring Cloud  基于Spring Boot, 提供了一些路由服务 和loadBalance差不多


--------------
防止重复提交
1> 提交后重定向到一个GET页面,避免F5刷新页面.
2> 进入表单页时生成一个token分别放在session和request中,表单页用hidden的方式将request中的token发送到服务端, 服务端比较session和传递过来的token是否相同,并将session中的token清除.

--------------
AOP(@Aspect) 和 自定义拦截器(HandlerInterceptorAdapter)的区别
自定义拦截器能获得用户的request信息.
而AOP需要获得的话只有通过传递用户参数到Service层才可以,或是threadLocal
AOP可以用作memcached的更新
自定义拦截器可以用于避免单一用户表单同时提交.(注意这里不是重复提交)

--------------------
NoSql精粹
noSql 特点 无模式, 集群, 牺牲了一致性
悲观锁处理并发时,很容易导致"死锁"

数据库分布式
1, 切片
2, 复制 (主从/对等--写入时一致性风险性太大)

映射-化简  Map-Reduce
将执行逻辑放到数据库集群中, 而不是在JVM客户端中

电子商务平台
--购物车及会话数据 [键值DB]
--已完成的订单 [文档DB]
--库存及产品价格 [关系型DB]
--客户社交关系图 [图DB] (您的朋友还购买了)

-----------------------


dao层定义属性最好使用int 而不是integer
数据库中为空时Integer直接用来判断 == 1 时会有空指针异常   而int 有个默认的值0

--------------
dao中用String 声明也有可能是null   用String propertyNo = "";  就没有问题
  • 大小: 26 KB
  • 大小: 24.6 KB
  • 大小: 31.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics