1. 实体类
- 动态更新数据,只更新有值的数据
@DynamicUpdate
- 将实体类映射为表,如果名字不匹配使用name=tablename
@Entity
- 将属性映射为主键,并设置自增
@Id @GenericValue
- 自动生成常用方法
@Data @Getter @Setter
安装lombok教程
- 该属性不会映射到库里
@Transient
- 不希望返回JSON的属性
@JsonIgnore
- 只返回非空的JSON
@JsonInclude
- 将JSON转换为List
gson.fromJSON(json,new TypeToken
>(){}.getType());
- 将日期转换为Long做法:新建一个类如下,再将实体类日期属性上加
@JsonSerialize(using=Date2LongSerializer.class)
public class Date2LongSerializer extends JsonSerializer {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeNumber(date.getTime() / 1000);
}
}
- 添加额外配置文件
@ImportResource({"classpath:xxx-context.xml","classpath:yyy-context.xml"})
- 添加额外属性文件
@PropertyResource({"classpath:xxx.properties","classpath:yyy.properties"})
- 读取属性文件,配置类型安全的bean
@Component
@ConfigurationProperties(prefix="book",location={"classpath:config/book.properties"})
2. 持久层
点击查看JPA语法
//创建持久层接口
//继承JpaRepository<对象,主键>自带基本的增删改查功能
//如果有特殊查询,请按照给定的语法,写出方法即可
//语法规则
public interface ProductInfoRepository extends JpaRepository {
List
- 更多内容参考第9章
2. 业务层
- 接口+实现类的方式
public interface DemoService {
//根据id获得对象
Object findOne(Integer id);
//获得所有对象,JPA会根据实体的相关注解进行查询
List
@Service
public class DemoServiceImpl implements DemoService {
//注入DAO层
@Autowired
private CtsDAO dao;
//实现方法的业务逻辑
@Override
public Object findById(Integer id) {
return dao.findById(id);
}
}
3. 控制层
- 类级注解
@RestController(返回Json格式专用) @RequestMapping("/*/*")
- 方法级注解
@GetMapping("/list")@PostMapping("/list")
@PutMapping() @DeleteMapping()
- 参数级注解
@RequestParam(value="id",defaultValue="1")String id
required=false,参数可为空
//get请求示例
@GetMapping("/list")
//指定参数和默认值
public ModelAndView list(@RequestParam(value="id",defaultValue="1")String id, Map map) {
List categoryList = categoryService.findAll();
//将数据放到map里
map.put("categoryList", categoryList);
//返回视图和map,供解析
return new ModelAndView("category/list", map);
}
//post请求示例
//使用表单验证类接收表单
@PostMapping("/save")
public ModelAndView save(@Valid CategoryForm form, BindingResult bindingResult, Map map) {
//...处理逻辑
//保存对象
service.save(productCategory);
//返回视图名和需要绑定的数据
return new ModelAndView("common/success", map);
}
//分页请求示例
/**
* 列表
* @param page 第几页, 从1页开始
* @param size 一页有多少条数据
* @return
*/
@GetMapping("/list")
public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size,
Map map) {
//分页请求对象(页码从0开始)
PageRequest request = new PageRequest(page - 1, size);
Page orderDTOPage = service.findList(request);
//将查询结果放入ModelAndView
map.put("orderDTOPage", orderDTOPage);
map.put("currentPage", page);
map.put("size", size);
return new ModelAndView("order/list", map);
}
- 以下为前后端分离写法,直接返回Json格式的数据
//通过接口返回值(前后端分离)
@GetMapping("/detail")
public ResultVOdetail(@RequestParam("id") String id ) {
OrderDTO orderDTO = service.findOne(id);
return ResultVOUtil.success(orderDTO);
}
//返回值工具类
public class ResultVOUtil {
public static ResultVO success(Object object) {
ResultVO resultVO = new ResultVO();
resultVO.setData(object);
resultVO.setCode(0);
resultVO.setMsg("成功");
return resultVO;
}
public static ResultVO success() {
return success(null);
}
public static ResultVO error(Integer code, String msg) {
ResultVO resultVO = new ResultVO();
resultVO.setCode(code);
resultVO.setMsg(msg);
return resultVO;
}
}
@Data
public class ResultVO {
/** 错误码. */
private Integer code;
/** 提示信息. */
private String msg;
/** 具体内容. */
private T data;
}
4. 表单验证类
- 建立一个实体验证类@Data @NotEmpty(message= "必填")非空验证
- 在controller接收方法参数里加上@Valid 验证类 用BindingResult对象接收结果
@PostMapping("/create")
public ResultVO
5. 测试类
- 类级注解
@RunWith(SpringRunner.class) @SptingBootTest @Slf4j
- 测试完毕就回滚 测试方法注解
@Test @Transactional
-
日志打印方法详情如下
log.debug("debug...");
log.info("name: " + name + " ,password: " + password);
log.info("name: {}, password: {}", name, password);
log.error("error...");
log.warn("warn..."); 拷贝属性BeanUtils.copyProperties(from,to)
6. AOP类
- 建立aop类,添加类级注解
@Aspect@Component
-
创建处理逻辑方法注解如下:先定义切入点,再对切入点操作
@PointCut("execution(public * com.xs.controller.RelateController.list(..))") public void log(){}切入点 @Before("log()")最先拦截 @After("log()")最后拦截 @AfterReturning("log()")结果通知 @AfterThrowing("log()")异常通知 @Around("log()")环绕通知 public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("进入环绕通知"); Object object = pjp.proceed();//执行该方法 System.out.println("退出方法"); return object; } 顺序:最先拦截>环绕入>log()>结果通知>环绕出>最后拦截
-
使用日志打印控制台:
private static final Logger logger = LoggerFactory.getLogger(类名.class) logger.info("XXX")
7. 枚举类
- 要点
- 一般有两个属性code,message,并加上@Getter注解
- 共有的方法提取到一个Integerface中实现
- 通过使用枚举类得到信息,例如数据库里是0和1,要得到对应的是和否,可通过如下几段代码
//步骤一
//首先要有一个枚举类
//继承下段代码接口
@Getter
public enum ResultEnum extends CodeEnum{
SUCCESS(0, "是"),
PARAM_ERROR(1, "否"),
;
private Integer code;
private String message;
//通过构造方法
ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
//提取获得枚举类共有方法
public interface CodeEnum {
T getCode();
}
//此工具类用于根据0和1来获取枚举常量
public class EnumUtil {
public static T getByCode(Integer code, Class enumClass) {
for (T each: enumClass.getEnumConstants()) {
if (code.equals(each.getCode())) {
return each;
}
}
return null;
}
}
//在对象里调用工具类,通过自身属性status来获取枚举常量
@JsonIgnore
public ResultEnum getResultEnum() {
return EnumUtil.getByCode(status, ResultEnum.class);
}
//最终在页面渲染时,通过这样来获取
${obj.getResultEnum.message}
8. 异常类
- 要点
- 继承RuntimeException
- 要有一个属性记录错误代码
- 可供传入枚举类的构造器,调用父类构造方法传递异常信息
//自定义异常类
public class SellException extends RuntimeException{
//记录异常代码
private Integer code;
//该构造器用来传入枚举类
public SellException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
}
//该构造器用来传入异常代码和异常信息
public SellException(Integer code, String message) {
super(message);
this.code = code;
}
}
//自定义全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value=Exception.class)
@ResponseBody
private Map exceptionHandler(HttpServletRequest req,Exception e){
Map map = new HashMap<>();
map.put("success", false);
map.put("errMsg", e.getMessage());
return map;
}
}
//调用方式
if (orderDTO == null) {
log.error("【取消订单】查不到改订单, orderId={}", orderId);
throw new SellException(ResultEnum.ORDER_NOT_EXIST);
}
9. Springboot兼容MyBatis
- 引入依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
com.alibaba
druid
1.0.9
mysql
mysql-connector-java
5.1.29
添加配置文件
# mybatis
# 与表关联的对象所在包
mybatis.type-aliases-package=com.ctsmgr.entity
# 下划线转驼峰
mybatis.configuration.map-underscore-to-camel-case=true
# mapper.xml所在目录
mybatis.mapperLocations = classpath:com/dao/*.xml
mybatis.configuration.default-statement-timeout=3000
mybatis.configuration.default-fetch-size=100
# druid
spring.datasource.url=jdbc:mysql://localhost/blog?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive=2
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20
启动类
写一个mapper接口,注解sql的方式,该方法名可自定义,执行的方法由注解传入,如:
//插入方式一:传递Map(参数名称对应KEY值)
@Mapper
public interface ProductMapper{
@Insert(insert into CTS_RELATE_COMPANY (rela_comp_id,rela_comp_name) values(#{relaCompId,jdbcType=Integer},#{relaCompName,jdbcType=VARCHAR}))
int insertByMap(Mapmap);
}
//插入方式二:传递对象(参数名称对应属性名称)
@Mapper
public interface ProductMapper{
@Insert("insert into CTS_RELATE_COMPANY (rela_comp_id,rela_comp_name) values(#{relaCompId,jdbcType=Integer},#{relaCompName,jdbcType=VARCHAR})")
int insertByObject(CtsRelateCompany ctsRelateCompany);
}
//查询,如果返回多条记录用List接收
@Select("select * from CTS_RELATE_COMPANY where rela_comp_id = #{relaCompId}")
@Results({
@Result(Column="rela_comp_id",property="relaCompId"),
@Result(Column="rela_comp_name",property="relaCompName"),
})
ListfindById(Integer id);
//修改方式一:传递多参数,多个参数时需添加@Param注解
@Update("update CTS_RELATE_COMPANY set rela_comp_name = #{relaCompName} where rela_comp_id = #{relaCompId}")
int updateById(@Param("relaCompName")String name,@Param("relaCompId")Integer id);
//修改方式二:传递对象
@Update("update CTS_RELATE_COMPANY set rela_comp_name = #{relaCompName} where rela_comp_id = #{relaCompId}")
int updateByObject(CtsRelateCompany ctsRelateCompany);
//删除:
@Delete("delete from CTS_RELATE_COMPANY where rela_comp_id = #{relaCompId}")
int deleteById(Integer relaCompId);
- 如何调用Mapper?
//首先建立dao层
public class CtsRelateCompanyDAO{
@Autowired
CtsRelateCompanyDao dao;
public int insertByName(Mapmap){
return dao.insertByName(map);
}
}
//在service层里注入DAO并调用
- 返回主键
@Options(useGeneratedKeys=true, keyProperty="id",keyColumn="id")
10. 配置多数据源
- 配置属性文件
master 数据源配置
spring.datasource.url=jdbc:mysql://localhost/blog?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
slave 数据源配置
spring.datasource2.url=jdbc:mysql://localhost/blog2?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
spring.datasource2.username=root
spring.datasource2.password=123456
spring.datasource2.driverClassName=com.mysql.jdbc.Driver
- 实例化多个数据源(指定一个主数据源,并添加@Primary)
//主数据源配置类
@Configuration
//扫描mapper所在包
@MapperScan("springboot.start.db.company1.mapper")
public class MysqlDataSource1Config {
//实例化数据源
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
//实例化工厂类,并注入数据源
@Bean(name="primarySqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
//从数据源
@Configuration @MapperScan(basePackages="springboot.start.db.company2.mapper",sqlSessionFactoryRef="secondSqlSessionFactory")
public class MysqlDataSource2Config {
@Bean(name = "secondDataSource")
@ConfigurationProperties(prefix="spring.datasource2")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name = "secondSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
//配置完毕,直接注入即可使用
@RestController
public class DbController {
@Autowired
private UserMapper dao;
@Autowired
private UserMapper2 dao2;
@GetMapping("/find/{id}")
public User find(@PathVariable("id")int id) {
return dao.findById(id);
}
@GetMapping("/find2/{id}")
public User find2(@PathVariable("id")int id) {
return dao2.findById(id);
}
}