1、postgreSql用了聚合函数,前面要select的列必须出现在聚集函数或者groupby里,不然它不知道怎么分配。
2、
create database coolsheep;
create table student(
id varchar(32) primary key not null,
name varchar(64) ,
age int2,
)
pgSQL模式可以看作是多个表的集合。
一个模式中可以包含表,视图,索引等。
insert into student(id,name) values(‘123456’,‘小明’),(“123457”,‘小红’),(“123458”,‘小红’);
select * from student where name = ‘小明’;
update student set name = ‘小明2号’ where name = ‘小明’;
delete from student where name = ‘小明2号’;
select * from student where name like ‘%小明%’;
//只找出4条数据。
select * from student limit 4;
select * from student order by age DESC;//ASC为升序,DESC为降序。
select * from student where name =‘小明’ group by age order by age DESC;
//group by必须放在where 语句之后,order by语句之前。
select student.id,count(age) form student group by age order by age DESC;
with st as (select * from student) ,tc as (select * from teach) select st.id,tc.id from st,tc
select * from student group by name having count(name) >1 order by age desc;
select distinct name from student;
alter table student add sex int2;
alter table student drop column sex;
truncate student;//清空表数据
create view student_view as select * from student;
drop view student_view;
@Accessors(chain=true)加上后就可以开启链式编程,解决了开发中字段多个set要set多行的情况。
Person person = new Person();
person.setName(“王”).setSex(“女”).setEmail(“”)
3、RabbitMQ消息队列
消息队列是异步处理,降低耦合度,流量削峰。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UqQuRwZh-1666336577588)(未命名.assets/image-20220927154001623.png)]
RabbitMQ的五种工作模式
1、简单队列:一个生产者对应一个消费者。
2、work模式:一个生产者对应多个消费者,但是一条消息只能有一个消费者获得消息,轮询分发就是将消息队列中的消息,依次发送给所有消费者。一个消息只能被一个消费者获取。
3、发布/订阅模式(fanoutExchange):一个消费者将消息首先发送到交换机,交换机绑定到多个队列,然后被监听该队列的消费者所接收消费。如果没有队列绑定交换机,则消息丢失。
4、路由模式(DirectExchange):生产者将消息发送到direct交换机,在绑定队列和交换机的时候有一个路由key,生产者发送的消息会指定一个路由key,那么消息只会发送到相应key相同的队列中,接着监听该队列的消费者消费消息。也就是让消费者有选择性的接收消息。
5、主题模式(TopicExchange):路由模式是根据routingkey进行完整的匹配,而这里的通配符模式就是模糊匹配。与路由模式类似,但主题模式是一种模糊的匹配方式。
五种模式可以分为三类:
生产者,消息队列,一个消费者。
生产者,消息队列,多个消费者。
生产者,交换机,多个消息对列,多个消费者。
操作步骤:
1、导入maven依赖;
2、在application.yml引入rabbitmq的基本配置信息;
3、编写rabbitconfig类,类里面设置多个exchange,queue,routingkey,为了适用不同的使用场景。
Exchange:消息交换机,指定消息按什么规则,路由到哪个队列。
Binding:绑定,把exchange和queue按照路由规则绑定起来。
Queue:消息的载体,每个消息都会被投到一个或多个队列。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
4、编写消息的生产者
5、把交换机、队列、通过路由关键字进行绑定,写在rabbitconfig类当中。
针对消费者,设置交换机类型,将队列绑定到交换机。
FanoutExchange:将消息分发到所有的绑定队列,无routingkey的概念。用于发布/订阅模式。
DirectExchange:按照routingkey分发到指定队列。用于路由模式。
HeadersExchange:通过添加属性key-value匹配。
TopicExchange:多关键字匹配,模糊匹配。
6、编写消息的消费者
Fanout Exchange:
不处理路由键,只需要简单的将队列绑定到交换机上。
发送到交换机的消息都会被转发到该交换机绑定的所有队列上
Fanout交换机转发消息是最快的。
Fanout Exchange交换机可以简单的理解为广播站。
上面几句话,在生活中有个很常见的示例:在大学中,我们知道每天都会有广播站放出美妙的音乐。广播站是面向全校所有师生的,所有它的消息转发的是最快的。
Direct exchange:直连交换机。
定义:根据路由键(routingkey)需要完全匹配上才可以。会把消息路由到那些bingding key与routing key完全匹配的队列中。Rabbit mq默认的路由就是这种。
单个绑定示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a04K7Lzt-1666336577589)(未命名.assets/c2fdfc039245d6885380b1ef4b385f1bd01b24fe.jpeg@f_auto)]
说明:
我们可以看到有三个routingkey:orange、black、green.如果生产者P发送消息的key是orange(需要完全匹配的)那么将会被路由的Q1这个消费者上。如果发送的是black或者是green的时候,将会被路由到Q2上面。
多个绑定示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L7xAddTL-1666336577590)(未命名.assets/fd039245d688d43f6bbd76ad92e4f01e0ff43b5d.jpeg@f_auto)]
说明:
将相同的key绑定在不同的队列中。当生产者P发送消息key是black的时候,Q1和Q2都会被接收到。
消息手动应答,如果其中一个消费者挂掉,消息会放回队列给另一个消费者消费。
Topic主题模式:
//绑定信道
// * *(星号)可以代替一个单词
// * #(井号)可以替代零个或多个单词
channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");
HashMap<String, String> bindingKeymap = new HashMap<>();
bindingKeymap.put("quick.orange.rabbit","被队列Q1Q2接收到");
bindingKeymap.put("lazy.orange.elephant","被队列Q1Q2接收到");
bindingKeymap.put("lazy.pink.rabbit","虽然满足两个绑定,但只被队列Q2接收一次");
bindingKeymap.put("quick.brown.fox","不匹配任何绑定不会被任何队列接收到,会被丢弃");
bindingKeymap.put("quick.orange.male.rabbit","是四个单词不匹配任何绑定,会被丢弃");
bindingKeymap.put("lazy.orange.male.rabbit","被Q2接收到");
for (Map.Entry<String, String> bindingKeyEntry : bindingKeymap.entrySet()) {
String routingKey = bindingKeyEntry.getKey();
String message = bindingKeyEntry.getValue();
channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes("UTF-8"));
System.out.println("生产者发出消息:" + message);
}
消费者出现异常时,队列里面的消息无法进行消费,则消息就变成了死信。
先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。
在spring中,将组件注入ioc容器的方式通常分为两种
1、第一种也就是我们常用的@Component、@Controller、@ServicResponse以及@Respository注解。
2、使用@Bean注解来注入组件。
@Bean是一个方法级别上的注解,主要用在@Configuration和@Compoment注解的类里
两种方式的区别:
@Component注解作用于类上,而@Bean注解作用于配置类中的某一个方法上;
@Component表明告知Spring为当前的这个类创建一个bean,而@Bean表明告知Spring此方法将会返回一个对象,将返回的对象注入到容器中。
@Bean注解的使用更加灵活。
@Component泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。
@Value的作用
- @Value(${}) 用于获取配置文件中的值
- @Value(#{}) 用于获取属性中属性的值
springboot的几个注解作用。
如果想要创建bean实例,可以使用@Controller、@Service、@Repository、@Component等注解。
如果想要依赖注入某个对象,可以使用@Autowired和@Resource注解。
如果想要开启事务,可以使用@Transactional注解。
如果想要动态读取配置文件中的某个系统属性,可以使用@Value注解。
Ehcache是一个纯Java的进程内缓存框架。
- rabbit可以通过注解并发,例如在RabbitListeners注解上加入concurrency属性,concurrency="10"则并发数为10,有10个消费者。
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "myQueue1"),
exchange = @Exchange(value = "myExchange1"),
key = "routingKey1"
),
concurrency = "10"
)
public void process1(Message message) throws Exception {
// 执行程序
}
- 第二种方法时通过配置工厂的时候设置并发,rabbit低版本使用工厂并发,2.x等高版本直接使用注解设置并发。使用工厂方式设置并发,也可在RabbitListeners注解中设置参数containerFactory = “customContainerFactory”。
@Bean(customContainerFactory)
public RabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory mqConnectionFactory){
SimpleRabbitListenerContainerFactory listenerContainerFactory=new SimpleRabbitListenerContainerFactory();
listenerContainerFactory.setConnectionFactory(mqConnectionFactory);
listenerContainerFactory.setMessageConverter(new Jackson2JsonMessageConverter());
// 最大并发数
listenerContainerFactory.setMaxConcurrentConsumers(20);
// 初始并发数
listenerContainerFactory.setConcurrentConsumers(10);
return listenerContainerFactory;
}
rabbitmq管理面板的Queues中的features各参数解释。
D: durable的缩写,代表这个队列中的消息支持持久化.
AD: autoDelete的缩写,代表当前队列的最后一个消费者退订时被自动删除.注意:此时不管队列中是否还存在消息,队列都会删除.
TTL: 设置队列中的所有消息的生存周期,也可以在发布消息的时候为某个消息指定剩余生存时间,单位为毫秒.
DLX: 配置了x-dead-letter-exchange,当消息长度大于最大长度,或者过期等,将从队列中删除的消息推送到指定的交换机中去而不是丢弃.
DLK: x-dead-letter-routing-key的缩写,将删除的消息推送到指定交换机的指定路由键的队列中去.
// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
// autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
// return new Queue("TestDirectQueue",true,true,false);
死信就是消息在特定场景下的一种表现形式,这些场景包括:
- 消息被拒绝(basic.reject / basic.nack),并且requeue = false
- 消息的 TTL 过期时
- 消息队列达到最大长度
- 达到最大重试限制