feat: support photo likes (#1537)

* feat: support photo likes

* feat: add CacheLock annotation to likes api
pull/1541/head
guqing 2021-11-18 20:28:32 +08:00 committed by GitHub
parent e1737145ac
commit c149d53f7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 1 deletions

View File

@ -18,6 +18,8 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import run.halo.app.cache.lock.CacheLock;
import run.halo.app.cache.lock.CacheParam;
import run.halo.app.model.dto.PhotoDTO; import run.halo.app.model.dto.PhotoDTO;
import run.halo.app.model.entity.Photo; import run.halo.app.model.entity.Photo;
import run.halo.app.model.params.PhotoParam; import run.halo.app.model.params.PhotoParam;
@ -87,6 +89,13 @@ public class PhotoController {
return new PhotoDTO().convertFrom(photoService.update(photo)); return new PhotoDTO().convertFrom(photoService.update(photo));
} }
@PutMapping("{photoId:\\d+}/likes")
@ApiOperation("Likes a photo")
@CacheLock(autoDelete = false, traceRequest = true)
public void likes(@PathVariable @CacheParam Integer photoId) {
photoService.increaseLike(photoId);
}
@GetMapping("teams") @GetMapping("teams")
@ApiOperation("Lists all of photo teams") @ApiOperation("Lists all of photo teams")
public List<String> listTeams() { public List<String> listTeams() {

View File

@ -6,7 +6,10 @@ import run.halo.app.model.dto.base.OutputConverter;
import run.halo.app.model.entity.Photo; import run.halo.app.model.entity.Photo;
/** /**
* Photo dto.
*
* @author ryanwang * @author ryanwang
* @author guqing
* @date 2019-03-21 * @date 2019-03-21
*/ */
@Data @Data
@ -27,4 +30,6 @@ public class PhotoDTO implements OutputConverter<PhotoDTO, Photo> {
private String location; private String location;
private String description; private String description;
private Long likes;
} }

View File

@ -13,6 +13,7 @@ import javax.persistence.TemporalType;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
/** /**
@ -79,6 +80,13 @@ public class Photo extends BaseEntity {
@Column(name = "team") @Column(name = "team")
private String team; private String team;
/**
* Likes.
*/
@Column(name = "likes", nullable = false)
@ColumnDefault("0")
private Long likes;
@Override @Override
public void prePersist() { public void prePersist() {
super.prePersist(); super.prePersist();
@ -102,5 +110,9 @@ public class Photo extends BaseEntity {
if (team == null) { if (team == null) {
team = ""; team = "";
} }
if (likes == null || likes < 0) {
likes = 0L;
}
} }
} }

View File

@ -3,6 +3,7 @@ package run.halo.app.repository;
import java.util.List; import java.util.List;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import run.halo.app.model.entity.Photo; import run.halo.app.model.entity.Photo;
import run.halo.app.repository.base.BaseRepository; import run.halo.app.repository.base.BaseRepository;
@ -12,6 +13,7 @@ import run.halo.app.repository.base.BaseRepository;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @author guqing
* @date 2019-04-03 * @date 2019-04-03
*/ */
public interface PhotoRepository public interface PhotoRepository
@ -33,4 +35,15 @@ public interface PhotoRepository
*/ */
@Query(value = "select distinct p.team from Photo p") @Query(value = "select distinct p.team from Photo p")
List<String> findAllTeams(); List<String> findAllTeams();
/**
* Updates photo likes.
*
* @param likes likes delta
* @param photoId photo id must not be null
* @return updated rows
*/
@Modifying
@Query("update Photo p set p.likes = p.likes + :likes where p.id = :photoId")
int updateLikes(long likes, Integer photoId);
} }

View File

@ -79,4 +79,11 @@ public interface PhotoService extends CrudService<Photo, Integer> {
* @return list of teams * @return list of teams
*/ */
List<String> listAllTeams(); List<String> listAllTeams();
/**
* Increases photo likes(1).
*
* @param photoId photo id must not be null
*/
void increaseLike(Integer photoId);
} }

View File

@ -6,6 +6,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -13,7 +14,9 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import run.halo.app.exception.BadRequestException;
import run.halo.app.model.dto.PhotoDTO; import run.halo.app.model.dto.PhotoDTO;
import run.halo.app.model.entity.Photo; import run.halo.app.model.entity.Photo;
import run.halo.app.model.params.PhotoParam; import run.halo.app.model.params.PhotoParam;
@ -25,11 +28,13 @@ import run.halo.app.service.base.AbstractCrudService;
import run.halo.app.utils.ServiceUtils; import run.halo.app.utils.ServiceUtils;
/** /**
* PhotoService implementation class * PhotoService implementation class.
* *
* @author ryanwang * @author ryanwang
* @author guqing
* @date 2019-03-14 * @date 2019-03-14
*/ */
@Slf4j
@Service @Service
public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implements PhotoService { public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implements PhotoService {
@ -116,6 +121,20 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
return photoRepository.findAllTeams(); return photoRepository.findAllTeams();
} }
@Override
@Transactional
public void increaseLike(Integer photoId) {
Assert.notNull(photoId, "Photo id must not be null");
int affectedRows = photoRepository.updateLikes(1L, photoId);
if (affectedRows != 1) {
log.error("Photo with id: [{}] may not be found", photoId);
throw new BadRequestException(
"Failed to increase likes 1 for photo with id " + photoId);
}
}
@NonNull @NonNull
private Specification<Photo> buildSpecByQuery(@NonNull PhotoQuery photoQuery) { private Specification<Photo> buildSpecByQuery(@NonNull PhotoQuery photoQuery) {
Assert.notNull(photoQuery, "Photo query must not be null"); Assert.notNull(photoQuery, "Photo query must not be null");