sql脚本
sql
-- douban.tags_encode definition
CREATE TABLE `tags_encode` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`tag` varchar(100) NOT NULL COMMENT 'tag中文名',
`tag_encode` varchar(100) NOT NULL COMMENT 'tag转encode',
`type` varchar(100) NOT NULL DEFAULT 'movie' COMMENT '类型:movie、tv',
PRIMARY KEY (`id`),
UNIQUE KEY `tags_encode_un` (`tag`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='电影中文标签与encode后关系';
-- douban.movie definition
CREATE TABLE `movie` (
`id` bigint NOT NULL COMMENT '主键id,同步过来',
`episodes_info` varchar(100) DEFAULT NULL COMMENT 'episodes_info',
`rate` varchar(10) DEFAULT NULL COMMENT '评分',
`cover_x` int DEFAULT NULL COMMENT '横坐标',
`title` varchar(50) NOT NULL COMMENT '电影标题',
`url` varchar(100) NOT NULL COMMENT 'url地址',
`playable` tinyint(1) NOT NULL COMMENT '是否可播放',
`cover` varchar(100) NOT NULL COMMENT '图片地址',
`cover_y` varchar(100) DEFAULT NULL COMMENT '纵坐标',
`is_new` tinyint(1) NOT NULL COMMENT '是否为新上瘾',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='电影主表';
INSERT INTO douban.tags_encode (tag,tag_encode,`type`) VALUES
('热门','%E7%83%AD%E9%97%A8','movie'),
('最新','%E6%9C%80%E6%96%B0','movie'),
('豆瓣高分','%E8%B1%86%E7%93%A3%E9%AB%98%E5%88%86','movie'),
('冷门佳片','%E5%86%B7%E9%97%A8%E4%BD%B3%E7%89%87','movie'),
('华语','%E5%8D%8E%E8%AF%AD','movie'),
('欧美','%E6%AC%A7%E7%BE%8E','movie'),
('韩国','%E9%9F%A9%E5%9B%BD','movie'),
('日本','%E6%97%A5%E6%9C%AC','movie'),
('热门','%E7%83%AD%E9%97%A8','tv'),
('国产剧','%E5%9B%BD%E4%BA%A7%E5%89%A7','tv');
INSERT INTO douban.tags_encode (tag,tag_encode,`type`) VALUES
('综艺','%E7%BB%BC%E8%89%BA','tv'),
('美剧','%E7%BE%8E%E5%89%A7','tv'),
('日剧','%E6%97%A5%E5%89%A7','tv'),
('韩剧','%E9%9F%A9%E5%89%A7','tv'),
('日本动画','%E6%97%A5%E6%9C%AC%E5%8A%A8%E7%94%BB','tv'),
('纪录片','%E7%BA%AA%E5%BD%95%E7%89%87','tv');
获取所有电影标签:
https://movie.douban.com/j/search_tags?type=movie&source=index
获取所有tv标签:
https://movie.douban.com/j/search_tags?type=tv&source=index
获取所有热门标签电影:
https://movie.douban.com/j/search_subjects?type=movie\&tag=热门\&page_limit=500\&page_start=0
current->config->DoubanDbConfig
java
package com.pj.current.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* 从数据源配置
* 若需要配置更多数据源 , 直接在yml中添加数据源配置再增加相应的新的数据源配置类即可
*/
@Configuration
@MapperScan(basePackages = DoubanDbConfig.PACKAGE , sqlSessionFactoryRef = "doubanClusterSqlSessionFactory")
public class DoubanDbConfig {
private Logger logger = LoggerFactory.getLogger(DoubanDbConfig.class);
// 精确到 cluster 目录,以便跟其他数据源隔离
static final String PACKAGE = "com.pj.project.douban";
private static final String MAPPER_LOCATION = "classpath*:mapper/douban/*.xml";
private static final String DOMAIN_PACKAGE = "com.pj.project.douban";
@Value("${spring.datasource.url5}")
private String dbUrl;
@Value("${spring.datasource.username2}")
private String username;
@Value("${spring.datasource.password2}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Bean(name="doubanClusterDataSource") //声明其为Bean实例
public DataSource clusterDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
return datasource;
}
@Bean(name = "doubanClusterTransactionManager")
public DataSourceTransactionManager clusterTransactionManager() {
return new DataSourceTransactionManager(clusterDataSource());
}
@Bean(name = "doubanClusterSqlSessionFactory")
public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("doubanClusterDataSource") DataSource culsterDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(culsterDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(DoubanDbConfig.MAPPER_LOCATION));
sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE);
//mybatis 数据库字段与实体类属性驼峰映射配置
sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return sessionFactory.getObject();
}
}
MovieMapper
java
package com.pj.project.douban.movie;
import java.util.List;
import com.pj.models.so.SoMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* Mapper: movie -- 电影主表
* @author lizhihao
*/
@Mapper
@Repository
public interface MovieMapper {
/**
* 增
* @param m 实体对象
* @return 受影响行数
*/
int add(Movie m);
/**
* 删
* @param id 要删除的数据id
* @return 受影响行数
*/
int delete(Long id);
/**
* 改
* @param m 实体对象
* @return 受影响行数
*/
int update(Movie m);
/**
* 查 - 根据id
* @param id 要查询的数据id
* @return 实体对象
*/
Movie getById(Long id);
/**
* 查集合 - 根据条件(参数为空时代表忽略指定条件)
* @param so 参数集合
* @return 数据列表
*/
List<Movie> getList(SoMap so);
void batchInsertMovieAll(List<Movie> list);
void deleteAll();
}
DoubanMovieService
java
package com.pj.project.douban.movie;
import cn.hutool.core.net.URLEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class DoubanMovieService {
private static final String BASE_URL = "https://movie.douban.com/j/";
private static final String TAG_URL = "search_tags?type={type}&source={source}";
private static final String MOVIE_URL = "search_subjects?type={type}&tag={tag}&page_limit={page_limit}}&page_start={page_start}";
@Autowired
private RestTemplate restTemplate;
public List<String> getTags(){
List<String> result = new ArrayList<>(100);
Map<String, String> movieMap = new HashMap<>(10);
movieMap.put("type","movie");
movieMap.put("source","index");
List<String> movieTags = restTemplate.getForObject(BASE_URL + TAG_URL, List.class,movieMap);
Map<String, String> tvMap = new HashMap<>(10);
tvMap.put("type","tv");
tvMap.put("source","index");
List<String> tvTags = restTemplate.getForObject(BASE_URL + TAG_URL, List.class,tvMap);
result.addAll(movieTags);
result.addAll(tvTags);
return result;
}
public List<Movie> getMovies(String tag,int page_start,int page_limit){
Map<String, Object> movieMap = new HashMap<>(10);
movieMap.put("type","movie");
URLEncoder urlEncoder = new URLEncoder();
String encodeTag = urlEncoder.encode(tag, Charset.defaultCharset());
movieMap.put("tag",encodeTag);
movieMap.put("page_start",page_start);
movieMap.put("page_limit",page_limit);
return restTemplate.getForObject(BASE_URL + MOVIE_URL, List.class,movieMap);
}
}
Movie
java
package com.pj.project.douban.movie;
import java.io.Serializable;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Model: movie -- 电影主表
* @author lizhihao
*/
@Data
@Accessors(chain = true)
public class Movie implements Serializable {
// ---------- 模块常量 ----------
/**
* 序列化版本id
*/
private static final long serialVersionUID = 1L;
/**
* 此模块对应的表名
*/
public static final String TABLE_NAME = "movie";
/**
* 此模块对应的权限码
*/
public static final String PERMISSION_CODE = "movie";
// ---------- 表中字段 ----------
/**
* 主键id,同步过来
*/
public Long id;
/**
* episodes_info
*/
public String episodesInfo;
/**
* 评分
*/
public String rate;
/**
* 横坐标
*/
public Integer coverX;
/**
* 电影标题
*/
public String title;
/**
* url地址
*/
public String url;
/**
* 是否可播放
*/
public String playable;
/**
* 图片地址
*/
public String cover;
/**
* 纵坐标
*/
public String coverY;
/**
* 是否为新上瘾
*/
public String isNew;
}
MovieController
java
package com.pj.project.douban.movie;
import java.util.List;
import com.pj.models.so.SoMap;
import com.pj.project.douban.Douban_SP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.pj.utils.sg.*;
import com.pj.current.satoken.StpUserUtil;
import cn.dev33.satoken.annotation.SaCheckPermission;
/**
* Controller: movie -- 电影主表
* @author lizhihao
*/
@RestController
@RequestMapping("/v2/movie/")
public class MovieController {
/** 底层 Service 对象 */
@Autowired
MovieService movieService;
/** 增 */
@RequestMapping("add")
@SaCheckPermission(Movie.PERMISSION_CODE)
@Transactional(rollbackFor = Exception.class)
public AjaxJson add(Movie m){
movieService.add(m);
m = movieService.getById(Douban_SP.publicMapper.getPrimarykey());
return AjaxJson.getSuccessData(m);
}
/** 删 */
@RequestMapping("delete")
@SaCheckPermission(Movie.PERMISSION_CODE)
public AjaxJson delete(Long id){
int line = movieService.delete(id);
return AjaxJson.getByLine(line);
}
/** 删 - 根据id列表 */
@RequestMapping("deleteByIds")
@SaCheckPermission(Movie.PERMISSION_CODE)
public AjaxJson deleteByIds(){
List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
int line = Douban_SP.publicMapper.deleteByIds(Movie.TABLE_NAME, ids);
return AjaxJson.getByLine(line);
}
/** 改 */
@RequestMapping("update")
@SaCheckPermission(Movie.PERMISSION_CODE)
public AjaxJson update(Movie m){
int line = movieService.update(m);
return AjaxJson.getByLine(line);
}
/** 查 - 根据id */
@RequestMapping("getById")
public AjaxJson getById(Long id){
Movie m = movieService.getById(id);
return AjaxJson.getSuccessData(m);
}
/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
@RequestMapping("getList")
public AjaxJson getList() {
SoMap so = SoMap.getRequestSoMap();
List<Movie> list = movieService.getList(so.startPage());
return AjaxJson.getPageData(so.getDataCount(), list);
}
@GetMapping("in_theaters")
public AjaxJson in_theaters(@RequestParam("start") int start,@RequestParam("count") int count){
SoMap so = SoMap.getRequestSoMap();
so.set("pageNo",start);
so.set("pageSize",count);
List<Movie> list = movieService.getList(so.startPage());
return AjaxJson.getSuccessData(list);
}
@GetMapping("coming_soon")
public AjaxJson coming_soon(@RequestParam("start") int start,@RequestParam("count") int count){
SoMap so = SoMap.getRequestSoMap();
so.set("pageNo",start);
so.set("pageSize",count);
List<Movie> list = movieService.getList(so.startPage());
return AjaxJson.getSuccessData(list);
}
@GetMapping("top250")
public AjaxJson top250(@RequestParam("start") int start,@RequestParam("count") int count){
SoMap so = SoMap.getRequestSoMap();
so.set("pageNo",start);
so.set("pageSize",count);
List<Movie> list = movieService.getList(so.startPage());
return AjaxJson.getSuccessData(list);
}
// ------------------------- 前端接口 -------------------------
/** 改 - 不传不改 [G] */
@RequestMapping("updateByNotNull")
public AjaxJson updateByNotNull(Long id){
AjaxError.throwBy(true, "如需正常调用此接口,请删除此行代码");
// 鉴别身份,是否为数据创建者
long userId = Douban_SP.publicMapper.getColumnByIdToLong(Movie.TABLE_NAME, "user_id", id);
AjaxError.throwBy(userId != StpUserUtil.getLoginIdAsLong(), "此数据您无权限修改");
// 开始修改 (请只保留需要修改的字段)
SoMap so = SoMap.getRequestSoMap();
so.clearNotIn("id", "episodesInfo", "rate", "coverX", "title", "url", "playable", "cover", "coverY", "isNew").clearNull().humpToLineCase();
int line = Douban_SP.publicMapper.updateBySoMapById(Movie.TABLE_NAME, so, id);
return AjaxJson.getByLine(line);
}
}
MovieService
java
package com.pj.project.douban.movie;
import java.util.List;
import com.pj.models.so.SoMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
/**
* Service: movie -- 电影主表
* @author lizhihao
*/
@Service
public class MovieService {
/** 底层 Mapper 对象 */
@Autowired
MovieMapper movieMapper;
@Autowired
private DoubanMovieService doubanMovieService;
/** 增 */
int add(Movie m){
return movieMapper.add(m);
}
/** 删 */
int delete(Long id){
return movieMapper.delete(id);
}
/** 改 */
int update(Movie m){
return movieMapper.update(m);
}
/** 查 */
Movie getById(Long id){
return movieMapper.getById(id);
}
/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
List<Movie> getList(SoMap so) {
return movieMapper.getList(so);
}
public void batchInsertMovieAll(){
List<String> tags = doubanMovieService.getTags();
if(CollectionUtils.isEmpty(tags)){
return;
}
tags.stream().forEach(v->{
// 每种类型大概 100000w 条数据
int perTagMaxSize = 100000;
int pageLimit = 1000;
for (int i = 0; i < perTagMaxSize; i+=pageLimit) {
List<Movie> movies = doubanMovieService.getMovies(v, i, i + pageLimit);
movieMapper.batchInsertMovieAll(movies);
}
});
}
public void deleteAll(){
movieMapper.deleteAll();
}
}
MovieUtil
java
package com.pj.project.douban.movie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.pj.utils.sg.*;
/**
* 工具类:movie -- 电影主表
* @author lizhihao
*
*/
@Component
public class MovieUtil {
/** 底层 Mapper 对象 */
public static MovieMapper movieMapper;
@Autowired
private void setMovieMapper(MovieMapper movieMapper) {
MovieUtil.movieMapper = movieMapper;
}
/**
* 将一个 Movie 对象进行进行数据完整性校验 (方便add/update等接口数据校验) [G]
*/
static void check(Movie m) {
AjaxError.throwByIsNull(m.id, "[主键id,同步过来] 不能为空"); // 验证: 主键id,同步过来
AjaxError.throwByIsNull(m.episodesInfo, "[episodes_info] 不能为空"); // 验证: episodes_info
AjaxError.throwByIsNull(m.rate, "[评分] 不能为空"); // 验证: 评分
AjaxError.throwByIsNull(m.coverX, "[横坐标] 不能为空"); // 验证: 横坐标
AjaxError.throwByIsNull(m.title, "[电影标题] 不能为空"); // 验证: 电影标题
AjaxError.throwByIsNull(m.url, "[url地址] 不能为空"); // 验证: url地址
AjaxError.throwByIsNull(m.playable, "[是否可播放] 不能为空"); // 验证: 是否可播放
AjaxError.throwByIsNull(m.cover, "[图片地址] 不能为空"); // 验证: 图片地址
AjaxError.throwByIsNull(m.coverY, "[纵坐标] 不能为空"); // 验证: 纵坐标
AjaxError.throwByIsNull(m.isNew, "[是否为新上瘾] 不能为空"); // 验证: 是否为新上瘾
}
/**
* 获取一个Movie (方便复制代码用) [G]
*/
static Movie getMovie() {
Movie m = new Movie(); // 声明对象
m.id = 0L; // 主键id,同步过来
m.episodesInfo = ""; // episodes_info
m.rate = ""; // 评分
m.coverX = 0; // 横坐标
m.title = ""; // 电影标题
m.url = ""; // url地址
m.playable = ""; // 是否可播放
m.cover = ""; // 图片地址
m.coverY = ""; // 纵坐标
m.isNew = ""; // 是否为新上瘾
return m;
}
}
TagsEncodeMapper
java
package com.pj.project.douban.tags_encode;
import java.util.List;
import com.pj.models.so.SoMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* Mapper: tags_encode -- 电影中文标签与encode后关系
* @author lizhihao
*/
@Mapper
@Repository
public interface TagsEncodeMapper {
/**
* 增
* @param t 实体对象
* @return 受影响行数
*/
int add(TagsEncode t);
/**
* 删
* @param id 要删除的数据id
* @return 受影响行数
*/
int delete(Long id);
/**
* 改
* @param t 实体对象
* @return 受影响行数
*/
int update(TagsEncode t);
/**
* 查 - 根据id
* @param id 要查询的数据id
* @return 实体对象
*/
TagsEncode getById(Long id);
/**
* 查集合 - 根据条件(参数为空时代表忽略指定条件)
* @param so 参数集合
* @return 数据列表
*/
List<TagsEncode> getList(SoMap so);
}
TagsEncode
java
package com.pj.project.douban.tags_encode;
import java.io.Serializable;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Model: tags_encode -- 电影中文标签与encode后关系
* @author lizhihao
*/
@Data
@Accessors(chain = true)
public class TagsEncode implements Serializable {
// ---------- 模块常量 ----------
/**
* 序列化版本id
*/
private static final long serialVersionUID = 1L;
/**
* 此模块对应的表名
*/
public static final String TABLE_NAME = "tags_encode";
/**
* 此模块对应的权限码
*/
public static final String PERMISSION_CODE = "tags-encode";
// ---------- 表中字段 ----------
/**
* 自增主键
*/
public Long id;
/**
* tag中文名
*/
public String tag;
/**
* tag转encode
*/
public String tagEncode;
/**
* 类型:movie、tv
*/
public String type;
}
TagsEncodeController
java
package com.pj.project.douban.tags_encode;
import java.util.List;
import com.pj.models.so.SoMap;
import com.pj.project.douban.Douban_SP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.pj.utils.sg.*;
import com.pj.current.satoken.StpUserUtil;
import cn.dev33.satoken.annotation.SaCheckPermission;
/**
* Controller: tags_encode -- 电影中文标签与encode后关系
* @author lizhihao
*/
@RestController
@RequestMapping("/TagsEncode/")
public class TagsEncodeController {
/** 底层 Service 对象 */
@Autowired
TagsEncodeService tagsEncodeService;
/** 增 */
@RequestMapping("add")
@SaCheckPermission(TagsEncode.PERMISSION_CODE)
@Transactional(rollbackFor = Exception.class)
public AjaxJson add(TagsEncode t){
tagsEncodeService.add(t);
t = tagsEncodeService.getById(Douban_SP.publicMapper.getPrimarykey());
return AjaxJson.getSuccessData(t);
}
/** 删 */
@RequestMapping("delete")
@SaCheckPermission(TagsEncode.PERMISSION_CODE)
public AjaxJson delete(Long id){
int line = tagsEncodeService.delete(id);
return AjaxJson.getByLine(line);
}
/** 删 - 根据id列表 */
@RequestMapping("deleteByIds")
@SaCheckPermission(TagsEncode.PERMISSION_CODE)
public AjaxJson deleteByIds(){
List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
int line = Douban_SP.publicMapper.deleteByIds(TagsEncode.TABLE_NAME, ids);
return AjaxJson.getByLine(line);
}
/** 改 */
@RequestMapping("update")
@SaCheckPermission(TagsEncode.PERMISSION_CODE)
public AjaxJson update(TagsEncode t){
int line = tagsEncodeService.update(t);
return AjaxJson.getByLine(line);
}
/** 查 - 根据id */
@RequestMapping("getById")
public AjaxJson getById(Long id){
TagsEncode t = tagsEncodeService.getById(id);
return AjaxJson.getSuccessData(t);
}
/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
@RequestMapping("getList")
public AjaxJson getList() {
SoMap so = SoMap.getRequestSoMap();
List<TagsEncode> list = tagsEncodeService.getList(so.startPage());
return AjaxJson.getPageData(so.getDataCount(), list);
}
// ------------------------- 前端接口 -------------------------
/** 改 - 不传不改 [G] */
@RequestMapping("updateByNotNull")
public AjaxJson updateByNotNull(Long id){
AjaxError.throwBy(true, "如需正常调用此接口,请删除此行代码");
// 鉴别身份,是否为数据创建者
long userId = Douban_SP.publicMapper.getColumnByIdToLong(TagsEncode.TABLE_NAME, "user_id", id);
AjaxError.throwBy(userId != StpUserUtil.getLoginIdAsLong(), "此数据您无权限修改");
// 开始修改 (请只保留需要修改的字段)
SoMap so = SoMap.getRequestSoMap();
so.clearNotIn("id", "tag", "tagEncode", "type").clearNull().humpToLineCase();
int line = Douban_SP.publicMapper.updateBySoMapById(TagsEncode.TABLE_NAME, so, id);
return AjaxJson.getByLine(line);
}
}
TagsEncodeService
java
package com.pj.project.douban.tags_encode;
import java.util.List;
import com.pj.models.so.SoMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Service: tags_encode -- 电影中文标签与encode后关系
* @author lizhihao
*/
@Service
public class TagsEncodeService {
/** 底层 Mapper 对象 */
@Autowired
TagsEncodeMapper tagsEncodeMapper;
/** 增 */
int add(TagsEncode t){
return tagsEncodeMapper.add(t);
}
/** 删 */
int delete(Long id){
return tagsEncodeMapper.delete(id);
}
/** 改 */
int update(TagsEncode t){
return tagsEncodeMapper.update(t);
}
/** 查 */
TagsEncode getById(Long id){
return tagsEncodeMapper.getById(id);
}
/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
List<TagsEncode> getList(SoMap so) {
return tagsEncodeMapper.getList(so);
}
}
TagsEncodeUtil
java
package com.pj.project.douban.tags_encode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.pj.utils.sg.*;
/**
* 工具类:tags_encode -- 电影中文标签与encode后关系
* @author lizhihao
*
*/
@Component
public class TagsEncodeUtil {
/** 底层 Mapper 对象 */
public static TagsEncodeMapper tagsEncodeMapper;
@Autowired
private void setTagsEncodeMapper(TagsEncodeMapper tagsEncodeMapper) {
TagsEncodeUtil.tagsEncodeMapper = tagsEncodeMapper;
}
/**
* 将一个 TagsEncode 对象进行进行数据完整性校验 (方便add/update等接口数据校验) [G]
*/
static void check(TagsEncode t) {
AjaxError.throwByIsNull(t.id, "[自增主键] 不能为空"); // 验证: 自增主键
AjaxError.throwByIsNull(t.tag, "[tag中文名] 不能为空"); // 验证: tag中文名
AjaxError.throwByIsNull(t.tagEncode, "[tag转encode] 不能为空"); // 验证: tag转encode
AjaxError.throwByIsNull(t.type, "[类型:movie、tv] 不能为空"); // 验证: 类型:movie、tv
}
/**
* 获取一个TagsEncode (方便复制代码用) [G]
*/
static TagsEncode getTagsEncode() {
TagsEncode t = new TagsEncode(); // 声明对象
t.id = 0L; // 自增主键
t.tag = ""; // tag中文名
t.tagEncode = ""; // tag转encode
t.type = ""; // 类型:movie、tv
return t;
}
}
Douban_SP
java
package com.pj.project.douban;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pj.project.sp_dev.public4mapper.PublicMapper;
import com.pj.project.sp_dev.public4mapper.PublicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 公共Mapper 与 公共Service
* @author kong
*
*/
@Component
public class Douban_SP {
/**
* 公共Mapper
*/
public static PublicMapper publicMapper;
/**
* 公共Service
*/
public static PublicService publicService;
/**
* json序列化对象
*/
public static ObjectMapper objectMapper;
// 注入
@Autowired
public void setBean(
PublicMapper publicMapper,
PublicService publicService,
ObjectMapper objectMapper
) {
Douban_SP.publicMapper = publicMapper;
Douban_SP.publicService = publicService;
Douban_SP.objectMapper = objectMapper;
}
}
DoubanFC
java
package com.pj.project.douban;
import com.pj.project.douban.movie.MovieMapper;
import com.pj.project.douban.movie.MovieService;
import com.pj.project.sp_dev.public4mapper.PublicMapper;
import com.pj.project.sp_dev.public4mapper.PublicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class DoubanFC {
// ======================================== 所有Mapper ==============================================
public static MovieMapper movieMapper; // Mapper:电影主表
public static PublicMapper publicMapper; // Mapper: 公共Mapper
// ======================================== 所有Service ==============================================
public static MovieService movieService; // Service:电影主表
public static PublicService publicService; // Service:公共service
// ======================================== 所有注入所有Bean ==============================================
// 注入
@Autowired
public void setBean(
MovieMapper movieMapper,
PublicMapper publicMapper,
MovieService movieService,
PublicService publicService
) {
DoubanFC.movieMapper = movieMapper;
DoubanFC.publicMapper = publicMapper;
DoubanFC.movieService = movieService;
DoubanFC.publicService = publicService;
}
}
DoubanMovieTask
java
package com.pj.task;
import com.pj.project.douban.movie.MovieService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Component
public class DoubanMovieTask {
@Autowired
private MovieService movieService;
@Scheduled(cron = "0 0 23 * * ?")
@Transactional(rollbackFor = Exception.class)
public void syncAllMovie() {
try{
//先删除所有数据
movieService.deleteAll();
movieService.batchInsertMovieAll();
}catch (Exception e){
log.error("同步失败", e);
throw new RuntimeException("同步失败");
}
}
}
MovieMapper.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pj.project.douban.movie.MovieMapper">
<!-- 增 [G] -->
<insert id="add">
insert into
movie (id, episodes_info, rate, cover_x, title, url, playable, cover, cover_y, is_new)
values (#{id}, #{episodesInfo}, #{rate}, #{coverX}, #{title}, #{url}, #{playable}, #{cover}, #{coverY}, #{isNew})
</insert>
<insert id="batchInsertMovieAll" parameterType="java.util.List">
insert into
movie (id, episodes_info, rate, cover_x, title, url, playable, cover, cover_y, is_new)
VALUES
<foreach collection="list" item="l" separator=",">
(#{l.id}, #{l.episodesInfo}, #{l.rate}, #{l.coverX}, #{l.title}, #{l.url}, #{l.playable}, #{l.cover}, #{l.coverY}, #{l.isNew})
</foreach>
</insert>
<!-- 删 -->
<delete id="delete">
delete from movie
where id = #{id}
</delete>
<delete id="deleteAll">
delete from movie
</delete>
<!-- 改 [G] -->
<update id="update">
update movie set
id = #{id},
episodes_info = #{episodesInfo},
rate = #{rate},
cover_x = #{coverX},
title = #{title},
url = #{url},
playable = #{playable},
cover = #{cover},
cover_y = #{coverY},
is_new = #{isNew}
where id = #{id}
</update>
<!-- ================================== 查询相关 ================================== -->
<!-- select id, episodes_info, rate, cover_x, title, url, playable, cover, cover_y, is_new from movie -->
<!-- 通用映射:手动模式 -->
<resultMap id="model" type="com.pj.project.douban.movie.Movie">
<result property="id" column="id" />
<result property="episodesInfo" column="episodes_info" />
<result property="rate" column="rate" />
<result property="coverX" column="cover_x" />
<result property="title" column="title" />
<result property="url" column="url" />
<result property="playable" column="playable" />
<result property="cover" column="cover" />
<result property="coverY" column="cover_y" />
<result property="isNew" column="is_new" />
</resultMap>
<!-- 公共查询sql片段 -->
<sql id="select_sql">
select *
from movie
</sql>
<!-- 查 - 根据id -->
<select id="getById" resultMap="model">
<include refid="select_sql"></include>
where id = #{id}
</select>
<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
<select id="getList" resultMap="model">
<include refid="select_sql"></include>
<where>
<if test=' this.has("id") '> and id = #{id} </if>
<if test=' this.has("episodesInfo") '> and episodes_info = #{episodesInfo} </if>
<if test=' this.has("rate") '> and rate = #{rate} </if>
<if test=' this.has("coverX") '> and cover_x = #{coverX} </if>
<if test=' this.has("title") '> and title = #{title} </if>
<if test=' this.has("url") '> and url = #{url} </if>
<if test=' this.has("playable") '> and playable = #{playable} </if>
<if test=' this.has("cover") '> and cover = #{cover} </if>
<if test=' this.has("coverY") '> and cover_y = #{coverY} </if>
<if test=' this.has("isNew") '> and is_new = #{isNew} </if>
</where>
order by
<choose>
<when test='sortType == 1'> id desc </when>
<when test='sortType == 2'> episodes_info desc </when>
<when test='sortType == 3'> rate desc </when>
<when test='sortType == 4'> cover_x desc </when>
<when test='sortType == 5'> title desc </when>
<when test='sortType == 6'> url desc </when>
<when test='sortType == 7'> playable desc </when>
<when test='sortType == 8'> cover desc </when>
<when test='sortType == 9'> cover_y desc </when>
<when test='sortType == 10'> is_new desc </when>
<otherwise> id desc </otherwise>
</choose>
</select>
</mapper>
TagsEncodeMapper.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pj.project.douban.tags_encode.TagsEncodeMapper">
<!-- 增 [G] -->
<insert id="add">
insert into
tags_encode (id, tag, tag_encode, type)
values (#{id}, #{tag}, #{tagEncode}, #{type})
</insert>
<!-- 删 -->
<delete id="delete">
delete from tags_encode
where id = #{id}
</delete>
<!-- 改 [G] -->
<update id="update">
update tags_encode set
id = #{id},
tag = #{tag},
tag_encode = #{tagEncode},
type = #{type}
where id = #{id}
</update>
<!-- ================================== 查询相关 ================================== -->
<!-- select id, tag, tag_encode, type from tags_encode -->
<!-- 通用映射:手动模式 -->
<resultMap id="model" type="com.pj.project.douban.tags_encode.TagsEncode">
<result property="id" column="id" />
<result property="tag" column="tag" />
<result property="tagEncode" column="tag_encode" />
<result property="type" column="type" />
</resultMap>
<!-- 公共查询sql片段 -->
<sql id="select_sql">
select *
from tags_encode
</sql>
<!-- 查 - 根据id -->
<select id="getById" resultMap="model">
<include refid="select_sql"></include>
where id = #{id}
</select>
<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
<select id="getList" resultMap="model">
<include refid="select_sql"></include>
<where>
<if test=' this.has("id") '> and id = #{id} </if>
<if test=' this.has("tag") '> and tag = #{tag} </if>
<if test=' this.has("tagEncode") '> and tag_encode = #{tagEncode} </if>
<if test=' this.has("type") '> and type = #{type} </if>
</where>
order by
<choose>
<when test='sortType == 1'> id desc </when>
<when test='sortType == 2'> tag desc </when>
<when test='sortType == 3'> tag_encode desc </when>
<when test='sortType == 4'> type desc </when>
<otherwise> id desc </otherwise>
</choose>
</select>
</mapper>
java
url5: jdbc:mysql://localhost:3306/douban?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
username5: root
password5: 123456