release-对专辑及包含的歌曲的增删改查

release-2024-08-08
pikaqiudeshujia 9 months ago
parent e1dceeb0b8
commit c7fa98bd8e

@ -0,0 +1,35 @@
package enums;
import lombok.Getter;
/**
* @Author: yawei.huang
* @Package: enums
* @Project: luoo_parent
* @Date: 2024/4/28 15:09
* @Filename: AlbumStateEnum
* @Describe:
*/
@Getter
public enum AlbumStateEnum {
SAVE(0, "新建"),
IN_APPROVE(1, "待审核"),
BACK(2, "退回"),
WAIT_ARRIVE(3, "待上架"),
ARRIVED(4, "已上架")
;
private Integer code;
private String desc;
AlbumStateEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,29 @@
package enums;
import lombok.Getter;
/**
* @Author: yawei.huang
* @Package: enums
* @Project: luoo_parent
* @Date: 2024/4/28 14:27
* @Filename: SongInfoStateEnum
* @Describe:
*/
@Getter
public enum SongInfoStateEnum {
NO_USE("0", "停用"),
IN_USE("1", "启用")
;
private String code;
private String desc;
SongInfoStateEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,94 @@
package com.luoo.music.controller;
import api.PageResult;
import api.Result;
import com.luoo.music.dto.response.AlbumAddDTO;
import com.luoo.music.dto.response.AlbumSearchDTO;
import com.luoo.music.dto.response.AlbumSongAddDTO;
import com.luoo.music.dto.response.AlbumUpdateDTO;
import com.luoo.music.pojo.ArtistAlbum;
import com.luoo.music.service.AlbumService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.controller
* @Project: luoo_parent
* @Date: 2024/4/28 14:45
* @Filename: AlbumController
* @Describe:
*/
@RestController
@CrossOrigin
@Api(tags = "专辑")
@RequestMapping("/album")
public class AlbumController {
@Autowired
private AlbumService albumService;
@ApiOperation(value = "查询专辑", notes = "查询专辑")
@RequestMapping(value = "/list/{page}/{size}", method = RequestMethod.POST)
public Result<PageResult<ArtistAlbum>> search(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑查询对象", required = true) @RequestBody AlbumSearchDTO albumSearchDTO,
@ApiParam(value = "页码", required = true) @PathVariable Integer page,
@ApiParam(value = "每页条数", required = true) @PathVariable Integer size
) {
return Result.success(albumService.getList(albumSearchDTO, page, size));
}
@ApiOperation(value = "查询专辑详情", notes = "查询专辑详情")
@RequestMapping(value = "/one/{id}", method = RequestMethod.POST)
public Result<ArtistAlbum> getOne(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑id", required = true) @PathVariable String id) {
return Result.success(albumService.getOne(id));
}
@ApiOperation(value = "新增专辑", notes = "新增专辑")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<Void> add(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑信息", required = true) @RequestBody AlbumAddDTO addModel) {
albumService.addAlbum(token, addModel);
return Result.success();
}
@ApiOperation(value = "修改专辑", notes = "修改专辑")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public Result<Void> update(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑信息", required = true) @RequestBody AlbumUpdateDTO updateDTO) {
albumService.updateAlbum(token, updateDTO);
return Result.success();
}
@ApiOperation(value = "删除专辑", notes = "删除专辑")
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public Result<Void> delete(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑id", required = true) String id) {
albumService.deleteAlbum(id);
return Result.success();
}
@ApiOperation(value = "删除专辑中的歌曲", notes = "删除专辑中的歌曲")
@RequestMapping(value = "/delete/song", method = RequestMethod.POST)
public Result<Void> deleteAlbumSong(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑歌曲绑定的id", required = true) String id) {
albumService.deleteAlbumSong(id);
return Result.success();
}
@ApiOperation(value = "为专辑新增歌曲", notes = "为专辑新增歌曲")
@RequestMapping(value = "/add/Song/{id}", method = RequestMethod.POST)
public Result<Void> addNewSong(@ApiParam(value = "Header中的token信息", required = true) @RequestHeader("Authorization") String token,
@ApiParam(value = "专辑id") @PathVariable String id,
@ApiParam(value = "歌曲信息", required = true) @RequestBody AlbumSongAddDTO albumSongAddDTO) {
albumService.addNewSong(token, id, albumSongAddDTO);
return Result.success();
}
}

@ -3,6 +3,8 @@ package com.luoo.music.dao;
import com.luoo.music.pojo.ArtistAlbumSong; import com.luoo.music.pojo.ArtistAlbumSong;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
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;
/** /**
* @Author: yawei.huang * @Author: yawei.huang
@ -13,4 +15,8 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
* @Describe: * @Describe:
*/ */
public interface ArtistAlbumSongDao extends JpaRepository<ArtistAlbumSong, String>, JpaSpecificationExecutor<ArtistAlbumSong> { public interface ArtistAlbumSongDao extends JpaRepository<ArtistAlbumSong, String>, JpaSpecificationExecutor<ArtistAlbumSong> {
@Modifying
@Query(value = "delete from tb_artist_album_song where album_id = ?", nativeQuery = true)
void deleteByAlbumId(String albumId);
} }

@ -41,4 +41,10 @@ public interface SongInfoDao extends JpaRepository<SongInfo,String>, JpaSpecific
@Query(value = "select * from tb_song_info where match(name, artist, album) against(?1 IN BOOLEAN MODE) limit ?2,?3 ", nativeQuery = true) @Query(value = "select * from tb_song_info where match(name, artist, album) against(?1 IN BOOLEAN MODE) limit ?2,?3 ", nativeQuery = true)
List<SongInfo> fuzzySearch(String keyword, int offset, int limit); List<SongInfo> fuzzySearch(String keyword, int offset, int limit);
@Query(value = "select * from tb_song_info where id in (\n" +
" select song_id from tb_artist_album_song where album_id = ?\n" +
" \n" +
" )", nativeQuery = true)
List<SongInfo> findByAlbumId(String id);
} }

@ -0,0 +1,84 @@
package com.luoo.music.dto.response;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.dto.response
* @Project: luoo_parent
* @Date: 2024/4/28 13:00
* @Filename: AlbumAddDTO
* @Describe:
*/
@Data
public class AlbumAddDTO implements Serializable {
/**
*
*/
@ApiModelProperty("专辑名称")
@NotNull(message = "专辑名称不能为空")
private String name;
/**
*
*/
@ApiModelProperty("专辑封面")
@NotNull(message = "专辑封面不能为空")
private String image;
/**
*
*/
@ApiModelProperty("专辑版本")
private Integer version;
/**
*
*/
@ApiModelProperty("发行日期")
private Date publishDate;
/**
*
*/
@ApiModelProperty("主要风格")
@NotNull(message = "主要风格不能为空")
private String mainStyle;
/**
*
*/
@NotNull(message = "次要风格不能为空")
@ApiModelProperty("次要风格")
private String subStyle;
/**
*
*/
@ApiModelProperty("专辑条码")
private String barcode;
/**
*
*/
@ApiModelProperty("专辑描述")
private String description;
/**
* id
*/
@ApiModelProperty("音乐人id")
private String artistId;
/**
*
*/
@ApiModelProperty("音乐人昵称")
private String artistName;
/**
*
*/
@ApiModelProperty("歌曲新增对象")
private List<AlbumSongAddDTO> songAddList;
}

@ -0,0 +1,25 @@
package com.luoo.music.dto.response;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.dto.response
* @Project: luoo_parent
* @Date: 2024/4/28 15:26
* @Filename: AlbumSearchDTO
* @Describe:
*/
@Data
public class AlbumSearchDTO implements Serializable {
private String artistId;
private Integer state;
@ApiModelProperty("时间查询条件 null-全部时间1-今年2-最近一月3-最近一周4-最近24小时")
private Integer timeQuery;
}

@ -0,0 +1,57 @@
package com.luoo.music.dto.response;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.dto.response
* @Project: luoo_parent
* @Date: 2024/4/28 13:25
* @Filename: AlbumSongAddDTO
* @Describe:
*/
@Data
public class AlbumSongAddDTO implements Serializable {
@ApiModelProperty("歌曲名称")
@NotNull(message = "歌曲名称不能为空")
private String name;
@ApiModelProperty("语种")
@NotNull(message = "语种不能为空")
private Integer language;
@ApiModelProperty("曲风")
@NotNull(message = "曲风不能为空")
private List<String> tags;
@ApiModelProperty("售价")
@NotNull(message = "售价不能为空")
private float price;
@ApiModelProperty("作词")
private String lyricName;
@ApiModelProperty("作曲")
private String compositionName;
@ApiModelProperty("编曲")
private String arrangementName;
@ApiModelProperty("歌词")
private String lyric;
@ApiModelProperty("歌曲url")
@NotNull(message = "歌曲不能为空")
private String url;
@ApiModelProperty("mv")
private String mvUrl;
}

@ -0,0 +1,84 @@
package com.luoo.music.dto.response;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.dto.response
* @Project: luoo_parent
* @Date: 2024/4/28 13:00
* @Filename: AlbumAddDTO
* @Describe:
*/
@Data
public class AlbumUpdateDTO implements Serializable {
@NotNull
@ApiModelProperty("id")
private String id;
/**
*
*/
@ApiModelProperty("专辑名称")
@NotNull(message = "专辑名称不能为空")
private String name;
/**
*
*/
@ApiModelProperty("专辑封面")
@NotNull(message = "专辑封面不能为空")
private String image;
/**
*
*/
@ApiModelProperty("专辑版本")
private Integer version;
/**
*
*/
@ApiModelProperty("发行日期")
private Date publishDate;
/**
*
*/
@ApiModelProperty("主要风格")
@NotNull(message = "主要风格不能为空")
private String mainStyle;
/**
*
*/
@NotNull(message = "次要风格不能为空")
@ApiModelProperty("次要风格")
private String subStyle;
/**
*
*/
@ApiModelProperty("专辑条码")
private String barcode;
/**
*
*/
@ApiModelProperty("专辑描述")
private String description;
/**
* id
*/
@ApiModelProperty("音乐人id")
private String artistId;
/**
*
*/
@ApiModelProperty("音乐人昵称")
private String artistName;
}

@ -8,15 +8,14 @@ import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* *
*
* @TableName tb_artist_album * @TableName tb_artist_album
*/ */
@Data @Data
@ -39,6 +38,17 @@ public class ArtistAlbum implements Serializable {
*/ */
@ApiModelProperty("专辑名称") @ApiModelProperty("专辑名称")
private String name; private String name;
/**
*
*/
@ApiModelProperty("专辑封面")
private String image;
/**
*
*/
@ApiModelProperty("专辑状态")
private Integer state;
/** /**
* *
*/ */
@ -102,4 +112,10 @@ public class ArtistAlbum implements Serializable {
@ApiModelProperty("修改人") @ApiModelProperty("修改人")
private String updateUser; private String updateUser;
@Transient
@ApiModelProperty("专辑歌曲绑定关系")
private List<SongInfo> songList;
} }

@ -0,0 +1,311 @@
package com.luoo.music.service;
import api.PageResult;
import com.luoo.music.dao.ArtistAlbumDao;
import com.luoo.music.dao.ArtistAlbumSongDao;
import com.luoo.music.dao.SongInfoDao;
import com.luoo.music.dao.SongTagDao;
import com.luoo.music.dto.response.AlbumAddDTO;
import com.luoo.music.dto.response.AlbumSearchDTO;
import com.luoo.music.dto.response.AlbumSongAddDTO;
import com.luoo.music.dto.response.AlbumUpdateDTO;
import com.luoo.music.pojo.ArtistAlbum;
import com.luoo.music.pojo.ArtistAlbumSong;
import com.luoo.music.pojo.SongInfo;
import com.luoo.music.pojo.SongTag;
import com.luoo.music.util.Constants;
import dto.UserLoginDto;
import enums.AlbumStateEnum;
import enums.SongInfoStateEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.IdWorker;
import util.JwtUtil;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @Author: yawei.huang
* @Package: com.luoo.music.service
* @Project: luoo_parent
* @Date: 2024/4/28 11:27
* @Filename: AlbumService
* @Describe:
*/
@Service
@Slf4j
public class AlbumService {
@Autowired
private ArtistAlbumDao artistAlbumDao;
@Autowired
private ArtistAlbumSongDao artistAlbumSongDao;
@Autowired
private SongInfoDao songInfoDao;
@Autowired
private SongTagDao songTagDao;
@Autowired
private IdWorker idWorker;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private S3Service s3Service;
public PageResult<ArtistAlbum> getList(AlbumSearchDTO albumSearchDTO, Integer page, Integer size) {
List<ArtistAlbum> result = new ArrayList<>();
Sort sort = new Sort(Sort.Direction.DESC, "create_time");
PageRequest pageRequest = PageRequest.of(page - 1, size, sort);
Page<ArtistAlbum> albumPage;
if (!Objects.isNull(albumSearchDTO)) {
Specification<ArtistAlbum> artistAlbumSpecification = buildSearchSpecification(albumSearchDTO);
albumPage = artistAlbumDao.findAll(artistAlbumSpecification, pageRequest);
} else {
albumPage = artistAlbumDao.findAll(pageRequest);
}
long totalElements = albumPage.getTotalElements();
return new PageResult<>(totalElements, result);
}
/**
*
*
* @param param
* @return
*/
private Specification<ArtistAlbum> buildSearchSpecification(AlbumSearchDTO param) {
return (Root<ArtistAlbum> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
List<Predicate> predicateList = new ArrayList<Predicate>();
if (StringUtils.isNotBlank(param.getArtistId())) {
predicateList.add(builder.equal(root.get("artistId"), param.getArtistId()));
}
if (param.getState() != null) {
predicateList.add(builder.equal(root.get("state"), param.getState()));
}
switch (param.getTimeQuery()) {
case 1:
// 今年
LocalDate now = LocalDate.now();
int currentYear = now.getYear();
predicateList.add(builder.equal(builder.function("YEAR", Integer.class, root.get("createTime")), currentYear));
break;
case 2:
// 最近一月
LocalDate oneMonthAgo = LocalDate.now().minusMonths(1);
predicateList.add(builder.greaterThanOrEqualTo(root.get("createTime"), oneMonthAgo.atStartOfDay()));
break;
case 3:
// 最近一周
LocalDate oneWeekAgo = LocalDate.now().minusWeeks(1);
predicateList.add(builder.greaterThanOrEqualTo(root.get("createTime"), oneWeekAgo.atStartOfDay()));
break;
case 4:
// 24小时内
LocalDate oneDayAge = LocalDate.now().minusDays(1);
predicateList.add(builder.greaterThanOrEqualTo(root.get("createTime"), oneDayAge.atStartOfDay()));
break;
}
return builder.and(predicateList.toArray(new Predicate[predicateList.size()]));
};
}
/**
*
*
* @param id id
* @return list
*/
public ArtistAlbum getOne(String id) {
ArtistAlbum artistAlbum = artistAlbumDao.findById(id).get();
if (artistAlbum == null) {
throw new RuntimeException("专辑不存在,请刷新后重试");
}
List<SongInfo> songInfoList = songInfoDao.findByAlbumId(id);
artistAlbum.setSongList(songInfoList);
return artistAlbum;
}
/**
*
*
* @param token token
* @param albumAddDTO
*/
@Transactional(rollbackFor = Exception.class)
public void addAlbum(String token, AlbumAddDTO albumAddDTO) {
// 处理专辑对象
ArtistAlbum artistAlbum = new ArtistAlbum();
BeanUtils.copyProperties(albumAddDTO, artistAlbum);
artistAlbum.setId(String.valueOf(idWorker.nextId()));
UserLoginDto user = jwtUtil.getUserLoginDto(token);
if (user != null) {
artistAlbum.setCreateUser(user.getUserId());
} else {
throw new RuntimeException("用户校验失败,请重新登录");
}
artistAlbum.setState(AlbumStateEnum.SAVE.getCode());
artistAlbumDao.save(artistAlbum);
// 处理歌曲对象
List<AlbumSongAddDTO> songAddList = albumAddDTO.getSongAddList();
if (songAddList.isEmpty()) {
throw new RuntimeException("专辑音乐不能为空!");
} else {
for (AlbumSongAddDTO albumSongAddDTO : songAddList) {
addSongForAlbum(albumSongAddDTO, user, artistAlbum);
}
}
}
/**
*
*
* @param token token
* @param albumUpdateDTO
*/
@Transactional(rollbackFor = Exception.class)
public void updateAlbum(String token, AlbumUpdateDTO albumUpdateDTO) {
ArtistAlbum artistAlbum = new ArtistAlbum();
BeanUtils.copyProperties(albumUpdateDTO, artistAlbum);
UserLoginDto user = jwtUtil.getUserLoginDto(token);
if (user != null) {
artistAlbum.setUpdateUser(user.getUserId());
} else {
throw new RuntimeException("用户校验失败,请重新登录");
}
artistAlbumDao.save(artistAlbum);
}
/**
*
*
* @param id id
*/
@Transactional(rollbackFor = Exception.class)
public void deleteAlbum(String id) {
ArtistAlbum artistAlbum = artistAlbumDao.findById(id).get();
artistAlbumDao.delete(artistAlbum);
artistAlbumSongDao.deleteByAlbumId(id);
}
/**
* -
*
* @param id -id
*/
@Transactional(rollbackFor = Exception.class)
public void deleteAlbumSong(String id) {
ArtistAlbumSong artistAlbumSong = artistAlbumSongDao.findById(id).get();
if (artistAlbumSong.getId() == null) {
throw new RuntimeException("该专辑不存在此歌曲");
}
artistAlbumSongDao.delete(artistAlbumSong);
}
/**
*
*
* @param token token
* @param id id
* @param albumSongAddDTO
*/
@Transactional(rollbackFor = Exception.class)
public void addNewSong(String token, String id, AlbumSongAddDTO albumSongAddDTO) {
UserLoginDto user = jwtUtil.getUserLoginDto(token);
ArtistAlbum artistAlbum = artistAlbumDao.findById(id).get();
addSongForAlbum(albumSongAddDTO, user, artistAlbum);
}
/**
*
*
* @param albumSongAddDTO
* @param user
* @param artistAlbum
*/
private void addSongForAlbum(AlbumSongAddDTO albumSongAddDTO, UserLoginDto user, ArtistAlbum artistAlbum) {
String albumName = artistAlbum.getName();
String artistName = artistAlbum.getArtistName();
// 保存歌曲
SongInfo songInfo = new SongInfo();
BeanUtils.copyProperties(albumSongAddDTO, songInfo);
songInfo.setId(String.valueOf(idWorker.nextId()));
songInfo.setAlbum(albumName);
songInfo.setState(SongInfoStateEnum.IN_USE.getCode());
songInfo.setArtist(artistName);
if (user != null) {
artistAlbum.setCreateUser(user.getUserId());
} else {
throw new RuntimeException("用户校验失败,请重新登录");
}
songInfoDao.save(songInfo);
String id = songInfo.getId();
// 歌词上传处理lyricUrl字段
String lyric = songInfo.getLyric();
if (lyric != null) {
String lyricUrl = String.format("%s/%d%s", id, idWorker.nextId(), ".lyric");
String key = Constants.SONG_KEY_PREFIX + lyricUrl;
int upload = s3Service.uploadText(Constants.BUCKET, key, lyric);
songInfoDao.updateSongLyricAndUrl(id, lyric, lyricUrl);
}
// 曲风绑定
List<String> tags = albumSongAddDTO.getTags();
if (!tags.isEmpty()) {
songTagDao.deleteBySongId(id);
List<SongTag> songTagList = new ArrayList<>();
for (String item : tags) {
SongTag songTag = new SongTag();
songTag.setId(String.valueOf(idWorker.nextId()));
songTag.setSongId(id);
songTag.setTagId(item);
songTagList.add(songTag);
}
songTagDao.saveAll(songTagList);
}
// 专辑-音乐绑定
ArtistAlbumSong artistAlbumSong = ArtistAlbumSong.builder()
.id(String.valueOf(idWorker.nextId()))
.songId(id)
.albumId(artistAlbum.getId())
.build();
artistAlbumSongDao.save(artistAlbumSong);
}
}

@ -3,6 +3,8 @@ create table tb_artist_album
id varchar(20) not null id varchar(20) not null
primary key, primary key,
name varchar(255) null comment '专辑名称', name varchar(255) null comment '专辑名称',
image varchar(255) null comment '专辑封面',
state int null comment '专辑状态',
version int null comment '专辑版本', version int null comment '专辑版本',
publish_date date null comment '发行日期', publish_date date null comment '发行日期',
main_style varchar(500) null comment '主要风格', main_style varchar(500) null comment '主要风格',
@ -41,3 +43,8 @@ alter table tb_song_info
alter table tb_song_info alter table tb_song_info
add language int null comment '语种'; add language int null comment '语种';
alter table tb_song_info
add price float null comment '价格';

Loading…
Cancel
Save