Fork me on GitHub

使用 docker 安装 PostgreSQL 数据库(翻译)

原文地址: https://hackernoon.com/dont-install-postgres-docker-pull-postgres-bee20e200198

获取Postgres Docker镜像

1
docker pull postgres

:后跟上你上指定的镜像版本,上面的默认是postgres:latest

1
docker pull postgres:[tag_you_want]

创建目录将本地挂载点作为数据卷映射到容器内

1
mkdir -p $HOME/docker/volumes/postgres

运行Postgres容器

1
docker run --rm   --name pg-docker -e POSTGRES_PASSWORD=root -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data  postgres

以下翻译使用google翻译得来的,不太准确

我们为docker run命令提供了几个选项:

  • rm:退出时自动删除容器及其关联的文件系统。通常,如果我们运行大量短期容器,最好将rm标志传递给docker run命令以进行自动清理并避免磁盘空间问题。我们总是可以使用v选项(如下所述)将数据持久化到容器的生命周期之外
  • name:容器的标识名称。我们可以选择任何我们想要的名字。请注意,两个现有(即使它们已停止)容器不能具有相同的名称。要重新使用名称,您需要将rm标志传递给docker run命令,或者使用命令docker rm [container name]显式删除容器。
    -e:使用值docker将名称为POSTGRES_PASSWORD的环境变量暴露给容器。此环境变量设置PostgreSQL的超级用户密码。我们可以将POSTGRES_PASSWORD设置为我们喜欢的任何东西。我只是选择它作为船坞进行演示。您可以设置其他环境变量。这些包括POSTGRES_USER和POSTGRES_DB。POSTGRES_USER设置超级用户名。如果未提供,则超级用户名默认为postgres。POSTGRES_DB设置要设置的默认数据库的名称。如果未提供,则默认为POSTGRES_USER的值。
    -d:以分离模式或换句话说,在后台启动容器。
    -p:将localhost上的端口5432绑定到容器内的端口5432。此选项使运行在容器一侧的应用程序能够连接到在容器内运行的Postgres服务器。
    -v:将主机上的$ HOME / docker / volumes / postgres挂载到容器内创建的容器侧卷路径/ var / lib / postgresql / data中。这可确保即使在删除容器后postgres数据仍然存在。

连接到Postgres

一旦容器运行正常,从应用程序连接到该容器与连接到在docker容器外部运行的Postgres实例没有什么不同。例如,要使用psql进行连接,我们可以执行

1
psql -h localhost -U postgres -d postgres

产品观点

今天喝咖啡,听旁边人聊产品方向选择挺有意思,所以写下来

产品要比较竞品的优点,而不是缺点,从比较优点中找出区分点

比如淘宝就是全

而网易严选是闭着眼买不到差的

考拉的奶粉闭着眼买不到假的

虎扑上卖闭着眼买不到假的

严选只卖基本款,不给用户选择的机会

如果选择的产品方向是买到的都是真的要营造权威感,比如假设卖奶粉的公司是一家医药公司,会赢得客户的信任。

程序员如何自我学习?阿里资深技术专家这样做

原文地址: https://segmentfault.com/a/1190000015859552

作者:雷卷

小结:

1.阅读图书文档 2.视频学习 3.动手实践 4.熟练掌握工具 5.参加技术大会 6. 买个好电脑 - 来自阿里技术评论

摘要: 行业发展得太快,你必须学习,纯靠经验积累行不通,技术淘汰的速度远大于你经验积累的速度。 非鸡汤:不要和程序员谈自己的编程历史,很多的经验在今天已经不适用了。只要 2-3 年不关注技术,就基本快和程序员和编程绝缘啦,不是绝对,但是通常不会错。

阿里妹导读:互联网信息技术的迭代周期快是有目共睹的,因此,学习、更新知识这件事就变得相当重要。今天,阿里资深技术专家雷卷,将分享自己平时学习的方法和心得,希望能够带给大家一些启发(本文推荐养家糊口之外有点小追求的同学阅读,Ph.D、paper 秒懂的学霸同学可自动忽略~)。

1. 为何要持续学习,靠经验积累不行吗?

很多人都说程序员的薪资水平不错,可以媲美医生和律师。而程序员和医生、律师的不同点在于持续学习上。不是说医生和律师不需要学习,医生、律师能够凭之前的 case 积累非常多的经验(这也是大家看病喜欢找年纪大的医生的原因之一),而且这些经验很大程度上可以被复用(很多病因和判罚案例带有相似性)。

程序员这个职业则不同,主要是因为行业更新得太快,积累的经验很快就不适用了。

举几个例子:

如果你是 Java 程序员,且非常擅长 Struts + JSP 开发,解决了很多 Struts 框架的问题。但今天,这部分知识已经过时,需要重新学习。如果仍坚持使用之前的技术,会给同事和公司带来很大的技术负担。大家回顾一下自己从毕业到现在有多少技术都已经看不到踪影了。就阿里巴巴内部来说,很多技术也都已经被淘汰不用了。

就编程来说,有很多编程语言和门第之争。你在这个语言积累的经验到另外一个语言就未必行得通。我很少听说 Java 组招一个.Net 的资深工程师,即便有,那也是给产品做.Net SDK client 的。

软件的经验积累还会体现在一个架构设计上。很多同学会说经验积累得多,架构就设计得好,这在今天来说也未必。大家都在云上啦,云上提供的服务基本都是类似的,架构思路和使用的云上服务基本一致。

Amazon 的售前人员个个都是行业架构师,给你很好的架构和解决方案,包括迁移方案,所以你就知道架构的门槛了。非资深程序员可以花半天时间看一下 Learn how to design large-scale systems ( https://github.com/donnemarti... ),虽然说是 primer,但是还是非常实用的,配合一下 Awesome list ( https://github.com/topics/awe... ) 架构思路和模式都有了。框架和开发包的具体特性和对比了解了,一天就能够成为架构师。

有个笑话:一个产品经理找一个有个性的设计师去设计原型和交互稿。该设计师头都没有抬说道:“你抄的是哪个网站或 App? 告诉我,我下午给你做。”如果你看了 system design primer,当有架构师找你,你就可以说你参考的是哪个网站的架构。我们回头理解一下然后按照这个设计编写代码就可以了。在云上,架构设计基本都是 pattern 的,再花很多时间讨论架构设计,就有点想不通了。但对云上的产品做彻底的理解,这个还是需要的。 行业发展得太快,你必须学习,纯靠经验积累行不通,技术淘汰的速度远大于你经验积累的速度。

非鸡汤:不要和程序员谈自己的编程历史,很多的经验在今天已经不适用了。只要 2-3 年不关注技术,就基本快和程序员和编程绝缘啦,不是绝对,但是通常不会错。

2. 工具要非常熟练

有人跟我说:“不要吹啦,你就是 IDEA 使用得再熟练,也没有必要将学习和使用工具挂上钩吧。” 说句实在话,看到一些硅谷工程师的培训教程中他们对工具的熟练使用程度,我只能说我还是小白。

有一次和几个 google 的工程师吃饭聊天,问了一下他们遇到的哪些人比较牛? 一个工程师说他的 leader 太牛了,在帮助他找 bug 的时候,工具和 debug 使用的熟练程度让人眼花缭乱。很多工具都是他听都没有听过的,而且 Python 脚本编写几乎如行云流水般。究其原因并非是这个 leader 一眼就能看出问题所在,有些问题他也是第一次遇到,但他在单位时间内尝试的次数特别多,就很快把问题给逼出来了。

非鸡汤:在排查问题和写代码上,如果你 1 个小时只能尝试一种方法,别人却能够尝试 10 次,那么别人就是比你牛。天下武功唯快不破,你后续写 demo、查问题、工具的熟练程度都会决定你学习和尝试新事物的速度。

3. 读书 & 看文档

学习还需要系统化。并非单靠看一篇文章就能明白原理。

个人强烈推荐:

https://www.safaribooksonline.com/

Safari 应该是出版社联盟,IT 类图书基本都能找到。两个小问题是:需要收费,一年大概 400 刀;图书都是英文的。 Safari Books Online 的图书非常全,几乎涵盖绝大多数出版社,我们熟知 oreilly, apress, manning, packtpub,addison wiley,而且更新速度非常快。另外 Sarafi 提供的 Learn path 也非常有用,能帮助你系统地了解一些技术,如 blockchain,ai,machine learnging 等等。现在视频资料也非常多,包括专家知识培训和一些技术大会的视频。

阅读更多...

小白入门学习打日志

原文地址: 小白入门学习打日志

前言

只有光头才能变强。

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y

记得之前写过一篇:《阿里巴巴 Java开发手册》读后感,之前自学时由于没怎么接触过打“日志”,所以《手册》中的“日志规约”我就先放一边去了。

而之前写了一篇:在公司做的项目和自己在学校做的有什么区别?中就有提到:公司的项目不会有e.printStackTrace();这种代码的存在。因为这打印出来的错误信息没有日期、等级等等,分析起来不方便。

在工作中去服务器上查日志又是一个非常非常常见的操作,所以当初我又写了一篇 工作中常用到的Linux命令,里边就谈到了查日志时常用的Linux命令。

想着,既然接触日志也有一段时间了,不妨在回看《手册》,看看有什么要注意的地方,于是就有了这篇笔记。

一、Java打日志的基础

以前自己自学的时候,排查问题只会写下面的代码:

1
2
3
4
5
6
7
8
try {
// doSomething
} catch (Exception e) {
e.printStackTrace();
}
----------
// 查看某个数据的值时:
System.out.println(xxxx);

去到公司就发现上面的代码全不见了,剩下的是:

1
2
3
LOGGER.info("begin to run Java3y:{}", id);
----
LOGGER.error("excepiton occurs when run Java3y {}, exception{}", id, e.toString());

如果使用e.printStackTrace();的话,打印在控制的信息分析不方便:

打印在控制的信息分析不方便

而我们将信息分等级和时间记录在服务器的磁盘上,有问题了就可以根据对应的信息去查找相关的日志(这样排查起来是十分方便的):

服务器上的日志信息

我们再来看一下一般的日志长什么样的:

例如:现在有人来反馈某某某用户好像收不到短信,给出发送时间和用户ID,我们就可以在日志上找出该用户在我们系统的发送状态(例如图上的:state:81,我们就认为是发送成功状态)

谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使

用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘

撑爆,并记得及时删除这些观察日志。

大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。记录日志时请思考:这些

日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?

1.1什么叫做 打点 ?

打日志最常见的就是用来打印出程序执行时的相关信息,用于快速定位问题和排查问题。我一开始也是这么理解的,但是其实还可以延伸一下。

阅读更多...

Spring data jpa@query使用原生SQl,需要注意的坑

原文地址: https://blog.csdn.net/weixin_38608626/article/details/83183556

根据代码来解说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Query(value = "select bill.id_ as id, bill.created_date as date, bill.no, lawyer_case .case_no as caseNo, " +
"lawyer_case .case_name as caseName, customer.no as customerNo, customer.cn_name as customerName, " +
"bill.total_expense_after_tax, bill.collected_money, bill.book_ticket_amount, bill.version " +
"e1.name as creator, bill.status" +
"from bill " +
"left join lawyer_case on lawyer_case .case_no=bill.case_no " +
"left join customer on customer.no=bill.customer_no " +
"left join employee e1 on e1.id_=bill.creator " +
"where IF (?1!='', customer_no=?1, 1=1) " +
"and IF (?2!='', case_no=?2, 1=1) " +
"and IF (?3!='', status=?3, 1=1) " +
"and IF (?4!='', creator'%',?4,'%')), 1=1) " +
"and create_by=?5 " +
"ORDER BY ?#{#pageable} ",
countQuery = "select count(*) " +
"from bill " +
"left join lawyer_case on lawyer_case .case_no=bill.case_no " +
"left join customer on customer.no=bill.customer_no " +
"left join employee e1 on e1.id_=bill.creator " +
"where IF (?1!='', customer_no=?1, 1=1) " +
"and IF (?2!='', case_no=?2, 1=1) " +
"and IF (?3!='', status=?3, 1=1) " +
"and IF (?4!='', creator'%',?4,'%')), 1=1) " +
"and create_by=?5 "+
"ORDER BY ?#{#pageable} ",
nativeQuery = true)
Page<Object[]> findAllBill(String customerNo, String caseNo, Integer status, String creator,
String createBy, Pageable pageable);

需要注意的方法有以下几点:

1
2
3
4
5
6
7
8
1. From 不支持重命名.
2. 返回的是一个page<Object[]>,数组中只保存了数据,没有对应的key,只能根据返回数据的顺序,依次注入到DTO中。
3. 对于使用分页,需要:“ORDER BY ?#{#pageable}”,可以直接传入一个pageable对象,会自动解析。
4. 注意格式问题,很多时候就是换行的时候,没有空格。
5. 仔细对应数据库中表字段,很多时候报某个字段找不到,就是因为字段名写错,和数据库中对应不上。
6. 这是解决使用微服务,大量的数据都需要远程调用,会降低程序的性能。
7. 使用Pageabel作为参数的时候,去进行分页。刚开始的时候,觉得还是一个可行的办法,但是得注意的时候,当需要排序的时候,是无法加入sort字段的。 会一直报错left*。
8. 针对7的解决方案,把原生SQL的数据查询和countQuery分成两个查询方法。得到count,然后进行判断,若是等于0,则直接返回空集合;反之,则取获取数据。 需要自己进行分页计算,传入正确的pageNumber和pageSize。 大部分系统都是按照修改时间进行降序排序。 所以,order by可以写死。然后pageNumber和pageSize动态传入。 pageNumber的算法= (pageNumber - 1) * pageSize, 前提是PageNumber是从1开始,若0,则pageNumber=pageNumber * PageSize; 这样就可以保证数据的正确。
1
2
3
4
5
6
7
8
9
/**
* pageInfos: 转换之后的数据。
* pageable:传入的pageable.
* totalPage: 第一条SQL算好的返回值。
* 这样就可以统一的返回各种pageDTO。
*/
private Page<T> convertForPage(List<T> pageInfos, Pageable pageable, Integer totalPage) {
return new PageImpl<>(pageInfos, pageable, totalPage);
}

SpringBoot jpa多条件查询(参数可能为空)语句

原文地址 : https://blog.csdn.net/qq_36802726/article/details/81208853

1
2
3
@Query(value = "select * from xxx where if(?1 !='',x1=?1,1=1) and if(?2 !='',x2=?2,1=1)" +
"and if(?3 !='',x3=?3,1=1) ",nativeQuery = true)
List<XXX> find(String X1,String X2,String X3);

工作的时候需求有搜索功能,有三个参数,但是网上找了很多关于jpa多条件查询的代码要么在调dao的时候用了大量if判断,那么需要写很多查询方法,要么说的不知所云,我结合jpa和mysql原语句研究了半天才弄出了这个方法。

xxx是数据库表名,x1、x2、x3为查询的字段名。

下面的大写的XXX是实体类的名,X1X2X3为查询的参数。

if(?1 !=’’,x1=?1,1=1) 代表传入的参数X1如果不为””(Spring类型空是””而不是null)将参数传入x1,如果为空时显示1=1 代表参数为真,对查询结果不产生作用。

Java代码乱象!

原文地址: https://mp.weixin.qq.com/s/svYS4wNloWm25BrJH6KKXA

导读


查尔斯·狄更斯在《双城记》中写道:“这是一个最好的时代,也是一个最坏的时代。”

移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动;随着行业竞争加剧,互联网红利逐渐消失,很多创业公司九死一生。笔者在初创公司摸爬滚打数年,接触了各式各样的 Java 微服务架构,从中获得了一些优秀的理念,但也发现了一些不合理的现象。现在,笔者总结了一些创业公司存在的 Java 服务端乱象,并尝试性地给出了一些不成熟的建议。

1.使用Controller基类和Service基类

1.1.现象描述

1.1.1.Controller 基类

常见的 Controller 基类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/** 基础控制器类 */
public class BaseController {
/** 注入服务相关 */
/** 用户服务 */
@Autowired
protected UserService userService;
...

/** 静态常量相关 */
/** 手机号模式 */
protected static final String PHONE_PATTERN = "/^[1]([3-9])[0-9]{9}$/";
...

/** 静态函数相关 */
/** 验证电话 */
protected static vaildPhone(String phone) {...}
...
}

常见的 Controller 基类主要包含注入服务、静态常量和静态函数等,便于所有的Controller 继承它,并在函数中可以直接使用这些资源。

1.1.2. Service 基类

常见的 Service 基类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/** 基础服务类 */
public class BaseService {
/** 注入DAO相关 */
/** 用户DAO */
@Autowired
protected UserDAO userDAO;
...

/** 注入服务相关 */
/** 短信服务 */
@Autowired
protected SmsService smsService;
...

/** 注入参数相关 */
/** 系统名称 */
@Value("${example.systemName}")
protected String systemName;
...

/** 静态常量相关 */
/** 超级用户标识 */
protected static final long SUPPER_USER_ID = 0L;
...

/** 服务函数相关 */
/** 获取用户函数 */
protected UserDO getUser(Long userId) {...}
...

/** 静态函数相关 */
/** 获取用户名称 */
protected static String getUserName(UserDO user) {...}
...
}

常见的 Service 基类主要包括注入 DAO、注入服务、注入参数、静态常量、服务函数、静态函数等,便于所有的 Service 继承它,并在函数中可以直接使用这些资源。

1.2.论证基类必要性

首先,了解一下里氏替换原则:

里氏代换原则(Liskov Substitution Principle,简称LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。

其次,了解一下基类的优点:

  • 子类拥有父类的所有方法和属性,从而减少了创建子类的工作量;
  • 提高了代码的重用性,子类拥有父类的所有功能;
  • 提高了代码的扩展性,子类可以添加自己的功能。

所以,我们可以得出以下结论:

  • Controller 基类和 Service 基类在整个项目中并没有直接被使用,也就没有可使用其子类替换基类的场景,所以不满足里氏替换原则;
  • Controller 基类和 Service 基类并没有抽象接口函数或虚函数,即所有继承基类的子类间没有相关共性,直接导致在项目中仍然使用的是子类;
  • Controller 基类和 Service 基类只关注了重用性,即子类能够轻松使用基类的注入DAO、注入服务、注入参数、静态常量、服务函数、静态函数等资源。但是,忽略了这些资源的必要性,即这些资源并不是子类所必须的,反而给子类带来了加载时的性能损耗。

综上所述,Controller 基类和 Service 基类只是一个杂凑类,并不是一个真正意义上的基类,需要进行拆分。

1.3.拆分基类的方法

由于 Service 基类比 Controller 基类更典型,本文以 Service 基类举例说明如何来拆分“基类”。

1.3.1.把注入实例放入实现类

根据“使用即引入、无用则删除”原则,在需要使用的实现类中注入需要使用的DAO、服务和参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** 用户服务类 */
@Service
public class UserService {
/** 用户DAO */
@Autowired
private UserDAO userDAO;

/** 短信服务 */
@Autowired
private SmsService smsService;

/** 系统名称 */
@Value("${example.systemName}")
private String systemName;
...
}
阅读更多...
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信