1、IDEA如何添加数据库
DataGrip连接sqlserver,提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
添加Persistence
通过IDEA逆向生成实体类@Entity
在Persistence的项目中,右键选择“Generate Persistence Mapping”“By Database Schema”
用IDEA生成的工具生成的Model代码太多了,不便于查看。
初步优化方案:
package com.fcors.fcors.model;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.Date;
import java.util.Objects;
@Entity
@Getter
@Setter
@Table(name = "banner")
public class BannerEntity {
@Id
@Column(name = "id")
private Long id;
private String name;
private String description;
@Column(name = "create_time")
private Date createTime;
@Column(name = "update_time")
private Date updateTime;
@Column(name = "delete_time")
private Date deleteTime;
private String title;
private String img;
}
初步优化后,我们只需要在需要的时候,重新定义逻辑即可。
对于返回的Json存在两个明显不友好的问题,如何让Json的key是蛇形输出?如何让日期输出格式化?
jackson提供了方法,只需要在配置文件application.yml中定义即可
spring:
jackson:
serialization:
WRITE_DATES_AS_TIMESTAMPS: true
property-naming-strategy: UPPER_CAMEL_CASE
property-naming-strategy的类型
- LOWER_CAMEL_CASE userName 默认策略
- KEBAB_CASE user-name
- LOWER_CASE username
- SNAKE_CASE user_name
- UPPER_CAMEL_CASE UserName
IDEA生成的Model需要进行一些适配Java的修改
- int==>Long
- Timetamp===>Date
- byte===>Boolean
- 单体Json===>Object
- 多体Json===>List<Object>
上述的方案还存在一个问题,关于 createTime、updateTime和deleteTime,我们并不需要返回到前端。那怎么操作呢?
我们可以在参数前添加注解:@JsonIgnore
我们接着思考一个问题,每个表都有时间字段,那么我每次都要如此繁琐的操作吗?如何解决这些通用的问题
我们可以通过创建一个基类,然后Model继承它。
在model下创建一个基类BaseEntity
package com.fcors.fcors.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.util.Date;
@Getter
@Setter
@MappedSuperclass
public abstract class BaseEntity {
@JsonIgnore
@Column(name = "create_time")
private Date createTime;
@JsonIgnore
@Column(name = "update_time")
private Date updateTime;
@JsonIgnore
@Column(name = "delete_time")
private Date deleteTime;
}
原本model下面的BannerEntity 集成这个基类
package com.fcors.fcors.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ser.Serializers;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.Date;
import java.util.Objects;
@Entity
@Getter
@Setter
@Table(name = "banner")
public class BannerEntity extends BaseEntity {
@Id
@Column(name = "id")
private Long id;
private String name;
private String description;
private String title;
private String img;
}
2、实体类返回一个记录
根据数据库及业务逻辑,我们知道banner和bannerItem是属于一对多的关系,如果通过实体类的一对多,来实现输出该如何实现呢?
1、在model使用工具生成类BannerItemEntity
package com.fcors.fcors.model;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Getter
@Setter
@Table(name = "banner_item")
public class BannerItemEntity extends BaseEntity {
@Id
@Column(name = "id")
private Long id;
private String img;
private String keyword;
private short type;
private Long bannerId;
private String name;
}
2、修改model下面的BannerEntity,引入注解@OneToMany
package com.fcors.fcors.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
import java.util.Set;
@Entity
@Getter
@Setter
@Table(name = "banner")
public class BannerEntity extends BaseEntity {
@Id
@Column(name = "id")
private Long id;
private String name;
private String description;
private String title;
private String img;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="bannerId")
/* 设置懒加载 需要添加下面的注解 */
/* 后续我们可以编写vo的类来实现最终数据的过滤输出 */
private List<BannerItemEntity> bannerItemEntities;
}
Spu与Sku的关系也是1对多的关系,回忆一下如何处理?
- 创建一个Controller
- 创建一个Service和接口
- 创建一个Model绑定数据集成基类
- 创建一个Repository,集成JpaRepository<T,T>,建立Service与Model的关系
- 填写异常错误码
在api下创建一个Controller
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.model.SpuEntity;
import com.fcors.fcors.service.SpuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
@RestController
@RequestMapping("/spu/")
@Validated
public class SpuController {
@Autowired
private SpuService spuService;
@GetMapping("/id/{id}/detail")
public SpuEntity getOneByName(@PathVariable @Positive Long id){
SpuEntity spu = spuService.findOneById(id);
if(spu ==null){
throw new NotFoundException(30003);
}
return spu;
}
}
在service下面创建一个Service和接口
SpuService接口
package com.fcors.fcors.service;
import com.fcors.fcors.model.SpuEntity;
public interface SpuService {
SpuEntity findOneById(Long id);
}
SpuServiceImpl
package com.fcors.fcors.service;
import com.fcors.fcors.model.SpuEntity;
import com.fcors.fcors.repository.SpuRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SpuServiceImpl implements SpuService{
@Autowired
SpuRepository spuRepository;
@Override
public SpuEntity findOneById(Long id) {
return this.spuRepository.findOneById(id);
}
}
在model下创建一个Model绑定数据集成基类
package com.fcors.fcors.model;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Getter
@Setter
@Entity
@Table(name = "spu")
public class SpuEntity extends BaseEntity{
@Id
@Column(name = "id")
private Long id;
private String title;
private String subtitle;
private Long categoryId;
private Integer rootCategoryId;
private byte online;
private String price;
private Integer sketchSpecId;
private Integer defaultSkuId;
private String img;
private String discountPrice;
private String description;
private String tags;
private Byte isTest;
private String spuThemeImg;
private String forThemeImg;
}
在 Repository下创建SpuRepository
package com.fcors.fcors.repository;
import com.fcors.fcors.model.SpuEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/*JpaRepository<@value1,@value2>
* @value1:model类名
* @value:model的主键即表的主键
* */
@Repository
public interface SpuRepository extends JpaRepository<SpuEntity,Long> {
SpuEntity findOneById(Long id);
}
追加resource/config/exception-code.properties
fcors.codes[30003]=SpuId无记录
3、实体列返回一个列表
基于demo2,我们进行修改,并让它能返回一个Spu的list
- 在SpuRepository追加findAll方法
- 在service的接口和类中实现方法
- 在controller定义一个入口
在SpuRepository下面追加方法 findAll
package com.fcors.fcors.repository;
import com.fcors.fcors.model.SpuEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/*JpaRepository<@value1,@value2>
* @value1:model类名
* @value:model的主键即表的主键
* */
@Repository
public interface SpuRepository extends JpaRepository<SpuEntity,Long> {
SpuEntity findOneById(Long id);
List<SpuEntity> findAll();
}
分别在Service的接口和类引入这个方法
Service下的SpuService接口代码
package com.fcors.fcors.service;
import com.fcors.fcors.model.SpuEntity;
import java.util.List;
public interface SpuService {
SpuEntity findOneById(Long id);
List<SpuEntity> getLastPagingSpu();
}
Service下的SpuServiceImpl代码
package com.fcors.fcors.service;
import com.fcors.fcors.model.SpuEntity;
import com.fcors.fcors.repository.SpuRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SpuServiceImpl implements SpuService{
@Autowired
SpuRepository spuRepository;
@Override
public SpuEntity findOneById(Long id) {
return this.spuRepository.findOneById(id);
}
@Override
public List<SpuEntity> getLastPagingSpu() {
return this.spuRepository.findAll();
}
}
在SpuController定义一个入口
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.model.SpuEntity;
import com.fcors.fcors.service.SpuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
import java.util.List;
@RestController
@RequestMapping("/spu/")
@Validated
public class SpuController {
@Autowired
private SpuService spuService;
@GetMapping("/id/{id}/detail")
public SpuEntity getOneByName(@PathVariable @Positive Long id){
SpuEntity spu = spuService.findOneById(id);
if(spu ==null){
throw new NotFoundException(30003);
}
return spu;
}
@GetMapping("/latest")
public List<SpuEntity> getLastPagingSpu(){
List<SpuEntity> SpuList = this.spuService.getLastPagingSpu();
return SpuList;
}
}
如果我们可以实现按需要加载字段和加载懒加载的list呢?
关于JPA的乐观锁和悲观锁