Controller
@GetMapping("/alarm")
public Response<Page<AlarmResponse>> alarm(Pageable pageable, Authentication authentication) {
return Response.success(userService.alarmList(authentication.getName(), pageable).map(AlarmResponse::fromAlarm));
}
Service
@Transactional
public Page<Alarm> alarmList(String userName, Pageable pageable) {
UserEntity user = userRepository.findByUserName(userName).orElseThrow(
() -> new SimpleSnsApplicationException(ErrorCode.USER_NOT_FOUND, String.format("userName is %s", userName))
);
return alarmEntityRepository.findAllByUser(user, pageable).map(Alarm::fromEntity);
}
AlarmEntity
@Setter
@Getter
@Entity
@Table(name = "\"alarm\"")
@SQLDelete(sql = "UPDATE \"alarm\" SET removed_at = NOW() WHERE id=?")
@Where(clause = "removed_at is NULL")
@NoArgsConstructor
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
public class AlarmEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id = null;
//알람을 받는 사람
@ManyToOne
@JoinColumn(name = "user_id")
private UserEntity user;
@Enumerated(EnumType.STRING)
private AlarmType alarmType;
//누가 알람을 보냈는지, 알람을 발생시킨 post 정보
//앞으로 변화 가능성이 높으므로 type을 json으로 설정
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private AlarmArgs args;
@Column(name = "registered_at")
private Timestamp registeredAt;
@Column(name = "updated_at")
private Timestamp updatedAt;
@Column(name = "removed_at")
private Timestamp removedAt;
@PrePersist
void registeredAt() {
this.registeredAt = Timestamp.from(Instant.now());
}
@PreUpdate
void updatedAt() {
this.updatedAt = Timestamp.from(Instant.now());
}
public static AlarmEntity of(AlarmType alarmType, AlarmArgs args, UserEntity user) {
AlarmEntity entity = new AlarmEntity();
entity.setAlarmType(alarmType);
entity.setArgs(args);
entity.setUser(user);
return entity;
}
}
enum
@Getter
@AllArgsConstructor
public enum AlarmType {
NEW_COMMENT_ON_POST("new comment!"),
NEW_LIKE_ON_POST("new like!"),
;
private final String alarmText;
}
@Data
@AllArgsConstructor
public class AlarmArgs {
//알람을 발생시킨 사람
private Integer fromUserId;
//알람을 발생시킨 post
private Integer targetId;
}
AlarmEntityRepository
@Repository
public interface AlarmEntityRepository extends JpaRepository<AlarmEntity, Integer> {
Page<AlarmEntity> findAllByUser(UserEntity user, Pageable pageable);
}
Service- 댓글, 좋아요
@Transactional
public void comment(Integer postId, String userName, String comment) {
PostEntity postEntity = postEntityRepository.findById(postId).orElseThrow(() -> new SimpleSnsApplicationException(ErrorCode.POST_NOT_FOUND, String.format("postId is %d", postId)));
UserEntity userEntity = userEntityRepository.findByUserName(userName)
.orElseThrow(() -> new SimpleSnsApplicationException(ErrorCode.USER_NOT_FOUND, String.format("userName is %s", userName)));
commentEntityRepository.save(CommentEntity.of(comment, postEntity, userEntity));
// alarm 만들기
alarmEntityRepository.save(AlarmEntity.of(AlarmType.NEW_COMMENT_ON_POST, new AlarmArgs(userEntity.getId(), postId), postEntity.getUser()));
}
@Transactional
public void like(Integer postId, String userName) {
PostEntity postEntity = postEntityRepository.findById(postId).orElseThrow(() -> new SimpleSnsApplicationException(ErrorCode.POST_NOT_FOUND, String.format("postId is %d", postId)));
UserEntity userEntity = userEntityRepository.findByUserName(userName)
.orElseThrow(() -> new SimpleSnsApplicationException(ErrorCode.USER_NOT_FOUND, String.format("userName is %s", userName)));
likeEntityRepository.findByUserAndPost(userEntity, postEntity).ifPresent(it -> {
throw new SimpleSnsApplicationException(ErrorCode.ALREADY_LIKED_POST, String.format("userName %s already like the post %s", userName, postId));
});
likeEntityRepository.save(LikeEntity.of(postEntity, userEntity));
// alarm 만들기
alarmEntityRepository.save(AlarmEntity.of(AlarmType.NEW_LIKE_ON_POST, new AlarmArgs(userEntity.getId(), postId), postEntity.getUser()));
}