springboot入门简单使用

2023-10-27

1、SpringBoot项目创建并配置mysql数据库

创建项目

开发环境:idea

使用 Spring Initializer 可以快速生成 Spring Boot 应用

首先点击左上角,文件—新建—项目

image-20230511110042756

填写项目信息,注意:Java要选择8版本,然后点击下一步

image-20230511110427609

注释:需要安装的插件

Developer Tools选项下的Spring Boot DevTools和Lombok
Web选项下的Spring Web
SQL选项下的MySQL Driver

image-20230511111212840

看到左下角和右下角都没有进度条初始化项目后,并且右上角已经识别到了是一个Springboot项目后,项目即创建成功

image-20230511111518062

此时,启动一下项目,查看是否正常,提示如下字样即可以正常启动(端口:8080)

image-20230511111613762

使用浏览器打开网址吧,并能显示如下界面

localhost:8080

image-20230511111707686

编写Controller测试

新建TestController类,放在子包controller

image-20230511112047982

image-20230511112122798

新建好后,在里面编写添加如下代码

原始代码:

package com.example.mini_program_yln.controller;

public class TestController {
   
}

修改后

package com.example.mini_program_yln.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

//将数据以json格式返回给前端
@RestController
public class TestController {
    @GetMapping("/test")
    public String test() {
        return "Hello world!";
    }
}

重新启动下项目,访问

localhost:8080/test

image-20230511112530389

配置数据库

在resource目录下新建application.yml文件

image-20230511112755564

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 111111

解释:

需要修改的一般有数据库名、mysql账户、mysql密码

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/数据库名字?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: mysql的账号
    password: mysql的密码

这里需要提前使用navicat新建数据库

image-20230511113449360

2、SpringBoot集成mybatis-plus

官网:https://www.baomidou.com/

mybatis-plus是用来操作数据库的持久层框架

初始化数据库

按照官网的说法:操作

https://www.baomidou.com/pages/226c21/#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A5%E7%A8%8B

打开navicat(也可以使用idea链接mysql,也可以使用hedisql等其它工具连接),点击查询,选择刚才创建的的数据库

粘贴下面的代码后点击运行

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

image-20230511115825061

此时就自动创建好了user表,并插入了几条示例数据

image-20230511115935174

安装mybatis-plus

1、在pom.xml文件中引入依赖

<!--mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

image-20230511120143287

2、为了阻止恶意的全表更新删除,配置一下防全表更新与删除插件

针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除

在如下路径下新建一个软件包:config

image-20230511120420530

新建好如图所示

image-20230511120503979

然后在config包下新建MybatisPlusConfig

然后添加如下代码,并导入相关的类

@Configuration
public class MybatisPlusConfig {
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
  }
}

添加成功示例

package com.example.mini_program_yln.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
* 针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
* */
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        return interceptor;
    }
}

后续还可能要在这里添加分页配置

通过mybatis-plus将数据库数据通过接口显示

在下面的目录下新建entity子包

image-20230511121028366

然后再entity包下新建User类,添加如下代码

package com.example.mini_program_yln.entity;

import lombok.Data;

@Data
public class User {
    //表示id是主键,且插入数据时自增
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}


新建mapper子包

image-20230511123445106

新建UserMapper接口,去继承BaseMapper

package com.example.mini_program_yln.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mini_program_yln.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {



}

image-20230511123633482

我们去TestController.java文件测试下mapper

package com.example.mini_program_yln.controller;

import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//将数据以json格式返回给前端
@RestController
public class TestController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/testList")
    public List<User> testList() {
        return userMapper.selectList(null);
    }
}

访问http://localhost:8080/testList,返回了数据库User表的全部数据

image-20230511124201282

3、SpringBoot三层架构Controller、Service、Dao

image-20230511124751071

现在我们的项目还差service没有创建

image-20230511124922074

创建后

image-20230511125006504

在service包下新建IUserService接口,添加如下代码

image-20230511125032285

package com.example.mini_program_yln.servicce;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mini_program_yln.entity.User;

public interface IUserService extends IService<User> {
}

然后再service包下新建impl子包,并在impl包下新建UserServiceImpl

image-20230511125228789

添加如下代码

需要继承ServiceImpl,并实现自定义的IUserService

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}

4、SpringBoot集成Mabatis-plus编写增删改查接口

IUserService.java中编写代码,定义几个接口

package com.example.mini_program_yln.servicce;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mini_program_yln.entity.User;

import java.util.List;

public interface IUserService extends IService<User> {

    Page<User> page(Integer current, Integer size, String username);

    boolean saveOrUpdateById(User user);

    boolean deleteBatchIds(List<Integer> ids);

}

UserServiceImpl.java中实现一下几个接口

把鼠标放在红色波浪线这一行,点击实现方法即可,会自动生成方法体

image-20230511131319493

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

import java.util.List;

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    public Page<User> page(Integer current, Integer size, String username) {
        return null;
    }

    @Override
    public boolean saveOrUpdateById(User user) {
        return false;
    }

    @Override
    public boolean deleteBatchIds(List<Integer> ids) {
        return false;
    }
}

写一下逻辑的具体实现

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.DeleteBatchByIds;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

import javax.annotation.Resource;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    public Page<User> page(Integer current, Integer size, String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (!"".equals(username)) {
            //不为空
            //精确查询
            //wrapper.eq(User::getName,username);

            //模糊查询
            wrapper.like(User::getName, username);
        }
        Page<User> page = page(new Page<>(current, size), wrapper);
        return page;
    }

    @Override
    public boolean saveOrUpdateById(User user) {
        if (user.getId() != null) {
            //更新
            return updateById(user);
        } else {
            //新增
            return save(user);
        }
    }

    @Override
    public boolean deleteBatchIds(List<Integer> ids) {
        return removeByIds(ids);
    }
}

然后在controller包下新建UserController.java类

package com.example.mini_program_yln.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.servicce.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserServiceImpl userService;

    @GetMapping("/page")
    @Description("分页列表-模糊查询")
    public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
        return userService.page(current, size, username);
    }

    @PostMapping("/save")
    @Description("新增或更新")
    public boolean save(@RequestBody User user) {
        return userService.saveOrUpdateById(user);
    }

    @PostMapping("/delete")
    @Description("删除")
    public boolean delete(@RequestBody List<Integer> ids) {
        return userService.deleteBatchIds(ids);
    }

}

我们还需要在MybatisPlusConfig.java中新增分页配置项,增加下面的一行

public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());


        //分页配置
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));


        return interceptor;
    }
}

此时可以用postman测试接口了

其他

热部署集成

比如我们将代码从左图修改为右图,就需要编译重新启动才可以,这是对资源的浪费,而且耗时,这就需要用到热部署

image-20230511113951599

1、首先点击左上角:文件—设置

找到构建、执行、部署,点击编译器,勾选自动构建项目

image-20230511114143135

2、然后开启idea的动态自动编译(有些会自动开启,那就不需要操作)

image-20230511114411355

3、开启idea热部署策略

点击右上角项目—编辑配置

image-20230511114527757

点击修改选项

image-20230511114619574

执行更新操作时,修改为更新类和资源

image-20230511114646267

4、在pom文件中添加插件

<plugin>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-maven-plugin</artifactId>
     <configuration>
      <fork>true</fork>
              <addResources>true</addResources>
     </configuration>
</plugin>

image-20230511115105471

此时当idea失去焦点五秒后就会自动更新资源,完成了热部署

mybatis-plus日志打印

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

image-20230511135132103

跨域问题解决

方式一:在Controller类中加入注解

@CrossOrigin("*")
image-20230511135642302

有时Gradle的项目需要使用这个

@CrossOrigin(value = "*",allowCredentials = "true")

方式二:新建跨域配置项解决

在config包下新建CorsConfig

package com.example.mini_program_yln.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration // 一定不能忽略此注解
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        // 1.创建 CORS 配置对象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 支持请求方式
        config.addAllowedMethod("*");
        // 允许的原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露的头部信息
        config.addExposedHeader("*");
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}

SpringBoot项目配置多环境

在resources目录下新建两个文件:application-local.yamlapplication-dev.yaml

application.yaml

active表示当前所处环境:local表示本地开发环境,dev表示线上环境

可以对不同环境设置不同的mysql账号密码等

spring:
  profiles:
    active: dev

application-local.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

application-dev.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 1234567
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

SpringBoot返回结果统一封装

后端提供 RESTful API 给前端时,需要响应前端 API 调用是否成功:

  • 如果成功,成功的数据是什么。后续,前端会将数据渲染到页面上
  • 如果失败,失败的原因是什么。一般,前端会将原因弹出提示给用户

因此,需要有统一响应,而不能是每个接口定义自己的风格。一般来说,统一响应返回信息如下:

  • 成功时,返回成功的状态码 + 数据
  • 失败时,返回失败的状态码 + 错误提示

新建common子包

image-20230511150107275

common子包下创建CommonResult

package com.example.mini_program_yln.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult<T> {
    /**
     * 错误码
     */
    private Integer code;
    /**
     * 返回数据
     */
    private T data;
    /**
     * 错误提示,用户可阅读
     */
    private String msg;


    public static <T> CommonResult<T> success(T data) {
        CommonResult<T> result = new CommonResult<>();
        result.code = 0;
        result.data = data;
        result.msg = "";
        return result;
    }


    public static <T> CommonResult<T> error(Integer code, String message) {
        CommonResult<T> result = new CommonResult<>();
        result.code = code;
        result.msg = message;
        return result;
    }

    public static <T> CommonResult<T> error() {
        CommonResult<T> result = new CommonResult<>();
        result.code = 1;
        result.msg = "系统错误,请联系管理员";
        return result;
    }

}

测试一下

package com.example.mini_program_yln.controller;

import com.example.mini_program_yln.common.CommonResult;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//将数据以json格式返回给前端
@RestController
public class TestController {
    @Autowired
    private UserMapper userMapper;


    @Description("测试统一返回-成功")
    @GetMapping("/testResultSuccess")
    public CommonResult<List<User>> testResultSuccess() {
        return CommonResult.success(userMapper.selectList(null));
    }

    @Description("测试统一返回-失败")
    @GetMapping("/testResultError")
    public CommonResult<List<User>> testResultError() {
        return CommonResult.error(400, "失败了");
    }
}

分页封装

在common包下新建PageParam.java类

image-20230511152152629
package com.example.mini_program_yln.common;

import lombok.Data;

import java.io.Serializable;

@Data
public class PageParam implements Serializable {

    private static final Integer PAGE_NO = 1;
    private static final Integer PAGE_SIZE = 10;

    private Integer pageNo = PAGE_NO;

    private Integer pageSize = PAGE_SIZE;

}

之前分页的写法

@GetMapping("/page")
@Description("分页列表-模糊查询")
public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
    return userService.page(current, size, username);
}

现在的写法

@PostMapping("/pageFZ")
@Description("分页列表-分页封装")
public CommonResult<Page<User>> page(@RequestBody PageParam pageInfo) {
    Page<User> page = userService.page(
            new Page<>(pageInfo.getPageNo(), pageInfo.getPageSize())
    );
    return CommonResult.success(page);
}

参数校验

例如在上面的分页封装中,我们的pageSize需要一个范围,不能无限大

在pom文件中引入依赖

image-20230511154928859
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

然后修改PageParam.java文件

pageNo页码最小为1

pageSize最小为1,最大为100

package com.example.mini_program_yln.common;

import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Data
public class PageParam implements Serializable {

    private static final Integer PAGE_NO = 1;
    private static final Integer PAGE_SIZE = 10;

    @NotNull(message = "页码不能为空")
    @Min(value = 1, message = "页码最小值为 1")
    private Integer pageNo = PAGE_NO;

    @NotNull(message = "每页条数不能为空")
    @Min(value = 1, message = "每页条数最小值为 1")
    @Max(value = 100, message = "每页条数最大值为 100")
    private Integer pageSize = PAGE_SIZE;

}

测试接口发现确实可以校验,但是会返回一堆堆栈信息,这样并不好,可以进行全局异常捕获

image-20230511155102959

自定义异常和全局异常捕获

创建exception子包和GlobalExceptionHandler.java

image-20230511155258021

package com.example.mini_program_yln.exception;

import com.example.mini_program_yln.common.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /*
     *
     * 运行时异常
     * */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public CommonResult<?> ExceptionHandler() {
        return CommonResult.error();
    }


    /*
     *
     * 自定义异常
     * */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public CommonResult<?> CustomExceptionHandler(CustomException e) {

        return CommonResult.error(400, e.getMessage());
    }

    /**
     * 处理 SpringMVC 参数校验不正确
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult<?> methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) {
        FieldError fieldError = ex.getBindingResult().getFieldError();

        assert fieldError != null; // 断言,避免告警
        return CommonResult.error(400, String.format("请求参数不正确:%s:%s", fieldError.getField(), fieldError.getDefaultMessage()));
    }

    /**
     * 处理系统异常,兜底处理所有的一切
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
        // 返回 ERROR CommonResult
        return CommonResult.error(400, "未知异常,请联系管理员");
    }
}

此时分页参数传递错误,就可以正常捕获到

image-20230511162052981

自定义异常

在exception下创建CustomException.java类

package com.example.mini_program_yln.exception;

import lombok.Getter;

@Getter
public class CustomException extends RuntimeException {
    private Integer code;

    public CustomException(Integer code, String msg) {
        super(msg);
        this.code = code;
    }

    public CustomException( String msg) {
        super(msg);
        this.code = 400;
    }
}

代码中使用

@GetMapping("/page")
    @Description("分页列表-模糊查询")
    public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
        throw new CustomException(404,"aaa");
//        return userService.page(current, size, username);
    }

image-20230511162226132

自动生成entity实体类

在utils包下新建SqlHelper类

image-20230511163031279

使用之前一般需要修改packageOutPath、tablename、URL、NAME、PASS

package com.example.mini_program_yln.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 从数据库表反射出实体类,自动生成实体类
 *
 * @author xxxx
 */
public class SqlHelper {
    //基本数据配置
    private String packageOutPath = "com.example.mini_program_yln.entity";// 指定实体生成所在包的路径,要修改
    private String authorName = "xxxx";// 作者名字
    private String tablename = "news";// 表名,要修改
    private String[] colnames; // 列名数组
    private String[] colTypes; // 列名类型数组
    private String version = "V0.01"; // 版本
    private int[] colSizes; // 列名大小数组
    private boolean f_util = false; // 是否需要导入包java.util.*
    private boolean f_sql = false; // 是否需要导入包java.sql.*
    private boolean f_lang = false; // 是否需要导入包java.sql.*
    private String defaultPath = "/src/main/java/";
    // 数据库连接
    private static final String URL = "jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";//要修改
    private static final String NAME = "root";//要修改
    private static final String PASS = "123456";//要修改
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /*
     * 构造函数
     */
    public SqlHelper() {
        // 创建连接
        Connection con;
        // 查要生成实体类的表
        String sql = "select * from " + tablename;
        PreparedStatement pStemt = null;
        try {
            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            con = DriverManager.getConnection(URL, NAME, PASS);
            pStemt = con.prepareStatement(sql);
            ResultSetMetaData rsmd = pStemt.getMetaData();
            int size = rsmd.getColumnCount(); // 统计列
            colnames = new String[size];
            colTypes = new String[size];
            colSizes = new int[size];
            for (int i = 0; i < size; i++) {

                colnames[i] = rsmd.getColumnName(i + 1);
                colTypes[i] = rsmd.getColumnTypeName(i + 1);
                //自动生成包配置


                // if (colTypes[i].equalsIgnoreCase("datetime")) {
                // f_util = true;
                // }
                if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text")
                        || colTypes[i].equalsIgnoreCase("datetime") || colTypes[i].equalsIgnoreCase("time")
                        || colTypes[i].equalsIgnoreCase("date") || colTypes[i].equalsIgnoreCase("datetime2")) {
                    f_sql = true;
                }
                // if (colTypes[i].equalsIgnoreCase("int")) {
                // f_lang = true;
                // }
                colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
            }

            String content = parse(colnames, colTypes, colSizes);

            try {
                File directory = new File("");

                String path = this.getClass().getResource("").getPath();

                System.out.println(path);

                String outputPath = directory.getAbsolutePath() + this.defaultPath
                        + this.packageOutPath.replace(".", "/") + "/" + initcap(underlineToHump(tablename)) + ".java";
                System.out.println("执行完毕,生成路径为:" + outputPath);
                FileWriter fw = new FileWriter(outputPath);
                PrintWriter pw = new PrintWriter(fw);
                pw.println(content);
                pw.flush();
                pw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {

        }
    }

    /**
     * 功能:生成实体类主体代码
     *
     * @param colnames
     * @param colTypes
     * @param colSizes
     * @return
     */
    private String parse(String[] colnames, String[] colTypes, int[] colSizes) {
        StringBuffer sb = new StringBuffer();
        // 生成package包路径
        sb.append("package " + this.packageOutPath + ";\r\n");
        // 判断是否导入工具包
        if (f_util) {
            sb.append("import java.util.Date;\r\n");
        }
        if (f_sql) {
            sb.append("import java.sql.*;\r\n");
        }
        if (f_lang) {
            sb.append("import java.lang.*;\r\n");
        }
        sb.append("import lombok.Data;\r\n");

        sb.append("\r\n");
        // 注释部分
        sb.append("   /**\r\n");
        sb.append("    * @文件名称:" + initcap(underlineToHump(this.tablename)) + ".java\r\n");
        sb.append("    * @创建时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\r\n");
        sb.append("    * @创  建  人:" + this.authorName + " \r\n");
        sb.append("    * @文件描述:" + tablename + " 实体类\r\n");
        sb.append("    * @文件版本:" + this.version + " \r\n");
        sb.append("    */ \r\n");
        sb.append("\n\r\n@Data");
        // 实体部分
        sb.append("\npublic class " + initcap(underlineToHump(tablename)) + "{\r\n");
        processAllAttrs(sb);// 属性
//        processAllMethod(sb);// get set方法
        sb.append("}\r\n");

        // System.out.println(sb.toString());
        return sb.toString();
    }

    /**
     * 功能:生成所有属性
     *
     * @param sb
     */
    private void processAllAttrs(StringBuffer sb) {

        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + this.underlineToHump(colnames[i]) + ";\r\n");
        }

    }

    /**
     * 功能:生成所有方法
     *
     * @param sb
     */
//    private void processAllMethod(StringBuffer sb) {
//
//        for (int i = 0; i < colnames.length; i++) {
//            sb.append("\tpublic void set" + initcap(colnames[i]) + "(" + sqlType2JavaType(colTypes[i]) + " "
//                    + colnames[i] + "){\r\n");
//            sb.append("\tthis." + colnames[i] + "=" + colnames[i] + ";\r\n");
//            sb.append("\t}\r\n");
//            sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + initcap(colnames[i]) + "(){\r\n");
//            sb.append("\t\treturn " + colnames[i] + ";\r\n");
//            sb.append("\t}\r\n");
//        }
//
//    }

    /**
     * 功能:将输入字符串的首字母改成大写
     *
     * @param str
     * @return
     */
    private String initcap(String str) {

        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }

        return new String(ch);
    }

    /**
     * 功能:获得列的数据类型
     *
     * @param sqlType
     * @return
     */
    private String sqlType2JavaType(String sqlType) {

        if (sqlType.equalsIgnoreCase("bit")) {
            return "Boolean";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("money")
                || sqlType.equalsIgnoreCase("smallmoney") || sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("int identity")) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("image") || sqlType.equalsIgnoreCase("varbinary(max)")
                || sqlType.equalsIgnoreCase("varbinary") || sqlType.equalsIgnoreCase("udt")
                || sqlType.equalsIgnoreCase("binary")) {
            return "Byte[]";
        } else if (sqlType.equalsIgnoreCase("nchar") || sqlType.equalsIgnoreCase("nvarchar(max)")
                || sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nvarchar(ntext)")
                || sqlType.equalsIgnoreCase("uniqueidentifier") || sqlType.equalsIgnoreCase("xml")
                || sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("varchar(max)")
                || sqlType.equalsIgnoreCase("text") || sqlType.equalsIgnoreCase("varchar")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("real")) {
            return "Float";
        } else if (sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase("tinyint")) {
            return "Short";
        } else if (sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("datetime")
                || sqlType.equalsIgnoreCase("time") || sqlType.equalsIgnoreCase("datetime2")
                || sqlType.equalsIgnoreCase("timestamp")) {
            return "Date";
        } else {
            System.out.println("数据类型异常,类型为:" + sqlType);
        }

        return null;
    }

    /**
     * 下划线转驼峰
     *
     * @String para
     */
    private String underlineToHump(String para) {
        StringBuilder result = new StringBuilder();
        String a[] = para.split("_");
        for (String s : a) {
            if (result.length() == 0) {
                result.append(s.toLowerCase());
            } else {
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }


    /**
     * 出口 TODO
     *
     * @param args
     */
    public static void main(String[] args) {

        new SqlHelper();

    }
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot入门简单使用 的相关文章

  • ElasticBeanstalk Java,Spring 活动配置文件

    我正在尝试通过 AWS ElasticBeanstalk 启动 spring boot jar 一切正常 配置文件为 默认 有谁知道如何为 java ElasticBeanstalk 应用程序 不是 tomcat 设置活动配置文件 spri
  • Java程序中的数组奇怪的行为[重复]

    这个问题在这里已经有答案了 我遇到了这个 Java 程序及其以意想不到的方式运行 以下程序计算 int 数组中元素对之间的差异 import java util public class SetTest public static void
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • 解决错误:日志已在具有多个实例的atomikos中使用

    我仅在使用atomikos的实时服务器上遇到问题 在我的本地服务器上它工作得很好 我在服务器上面临的问题是 init 中出错 日志已在使用中 完整的异常堆栈跟踪 java lang RuntimeException Log already
  • 在数据流模板中调用 waitUntilFinish() 后可以运行代码吗?

    我有一个批处理 Apache Beam 作业 它从 GCS 获取文件作为输入 我的目标是根据执行后管道的状态将文件移动到两个 GCS 存储桶之一 如果管道执行成功 则将文件移动到存储桶 A 否则 如果管道在执行过程中出现任何未处理的异常 则
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • 如何为 Gson 编写自定义 JSON 反序列化器?

    我有一个 Java 类 用户 public class User int id String name Timestamp updateDate 我收到一个包含来自 Web 服务的用户对象的 JSON 列表 id 1 name Jonas
  • 一种使用 Java Robot API 和 Selenium WebDriver by Java 进行文件上传的解决方案

    我看到很多人在使用 Selenium WebDriver 的测试环境中上传文件时遇到问题 我使用 selenium WebDriver 和 java 也遇到了同样的问题 我终于找到了解决方案 所以我将其发布在这里希望对其他人有所帮助 当我需
  • 使用替换字符串中多个单词的最有效方法[重复]

    这个问题在这里已经有答案了 此刻我正在做 Example line replaceAll replaceAll cat dog replaceAll football rugby 我觉得那很丑 不确定有更好的方法吗 也许循环遍历哈希图 ED
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • 序列化对象以进行单元测试

    假设在单元测试中我需要一个对象 其中所有 50 个字段都设置了一些值 我不想手动设置所有这些字段 因为这需要时间而且很烦人 不知何故 我需要获得一个实例 其中所有字段都由一些非空值初始化 我有一个想法 如果我要调试一些代码 在某个时候我会得
  • 在具有相同属性名称的不同数据类型上使用 ModelMapper

    我有两节课说Animal AnimalDto我想用ModelMapper将 Entity 转换为 DTO 反之亦然 但是对于具有相似名称的一些属性 这些类应该具有不同的数据类型 我该如何实现这一目标 动物 java public class
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • 检查 protobuf 消息 - 如何按名称获取字段值?

    我似乎无法找到一种方法来验证 protobuf 消息中字段的值 而无需显式调用其 getter 我看到周围的例子使用Descriptors FieldDescriptor实例到达消息映射内部 但它们要么基于迭代器 要么由字段号驱动 一旦我有
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • 使用 SAX 进行 XML 解析 |如何处理特殊字符?

    我们有一个 JAVA 应用程序 可以从 SAP 系统中提取数据 解析数据并呈现给用户 使用 SAP JCo 连接器提取数据 最近我们抛出了一个异常 org xml sax SAXParseException 字符引用 是无效的 XML 字符
  • 将 JSON 参数从 java 发布到 sinatra 服务

    我有一个 Android 应用程序发布到我的 sinatra 服务 早些时候 我无法读取 sinatra 服务上的参数 但是 在我将内容类型设置为 x www form urlencoded 之后 我能够看到参数 但不完全是我想要的 我在
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是

随机推荐

  • P1025 [NOIP2001 提高组] 数的划分(dfs搜有顺序)

    NOIP2001 提高组 数的划分 洛谷 include
  • 网络数据包的抓包(解析数据包内容)

    使用原始套接字接收 recvfrom reav read等 时 可以接收到完整的数据包 数据组装 拆解过程 数字代表上层协议的类型 完整数据包为 传输数据包内容 链路层包头 网络层包头 传输层包头 应用层数据 Ethernet MAC 封包
  • Python 面向对象(一)

    0 OOP Python面向对象 Python面向对象 面向对象编程 基础 公有私有 继承 组合 Mixin 魔法函数 魔法函数概述 构造类魔法函数 运算类魔法函数 1 面向对象概述 ObjectOriented OO OOP思想 接触到任
  • python每日一题

    写两个函数 分别求两个整数的最大公约数和最小公倍数 用主函数调用这两个函数 并输出结果两个整数由键盘输入 输入格式 两个数 输出格式 最大公约数 最小公倍数 样例输入 6 15 样例输出 3 30 注 gcd 最大公约数 lcm 最小公倍数
  • sql数据库中的 delete 与drop的区别

    数据库中的delete 与drop的区别 从下面的例子开始 delete delete from 表名 where 条件 drop alter table 表名 drop 字段 drop table 表 有的同学从从上面的例子 可以看出来
  • Java常用类:BigInteger和BigDecimal类

    目录 1 BigInteger类 2 BigDecimal类 1 BigInteger类 当需要很大的整数 long不够用时 可以使用BigInteger类来搞定 1 在对BigInteger 进行加减乘除时 需要使用对应的方法 2 可以创
  • .NET 6 VS2022连接WebService 生成代理客户端代码

    NET 6 VS2022连接WebService 生成代理客户端代码 VS2022安装 WCF Windows Communication Foundation 首先我们得安装WCF连接工具 搜索WCF并安装 安装完毕后启动VS2022 W
  • 华为OD机试真题- 递增字符串【2023Q1】【JAVA、Python、C++】

    题目描述 定义字符串完全由 A 和 B 组成 当然也可以全是 A 或全是 B 如果字符串从前往后都是以字典序排列的 那么我们称之为严格递增字符串 给出一个字符串s 允许修改字符串中的任意字符 即可以将任何的 A 修改成 B 也可以将任何的
  • [SHELL] shell 实现多进程后,如何等待所有进程结束

    1 gt 多进程实现 主要方法是使用 符号 将命令fork到后台执行 2 gt 等待结束的方法 2 1 使用 wait 命令 bin bash sleep 10 echo 1 gt gt s lock sleep 12 echo 1 gt
  • 计算机网络基础 1.0 -- 概述

    概念理解 报文 在网络中发送的数据块成为报文 在发送报文之前 通常会把数组分组 每个组都有个包头和数据组成 包头中包含了诸如目标地址和源地址等重要信息 这样才保证了数据能够有目的的在网络中的传输 主机是用户用来处理信息的 而路由器则是用来转
  • springboot 整合logback,设置日志的输出路径

    一 logback配置相对路径 项目实战中 配置成这种模式 打成jar包执行 生成的logs目录和jar包在同一目录下 即平级状态 1 1 配置成logs 查看效果 1 2 配置成 logs 1 配置成 logs 2 生成结果 工程所在磁盘
  • Win10 wsl-安装教程

    一 安装原生Win10 1 网上随便找一个win10版本 制作成U盘启动 并完成安装 2 安装原生的win10 上述方案安装的win10不是原生的 存在各种问题 进入win10操作系统 下载最新的 MediaCreationTool 工具
  • webpack-----前端必会高频面试题

    webpack学习总结 面试题 1 什么是webpack 静态模块打包工具 2 webpack作用 分析 压缩 打包代码 3 webpack好处 减少文件体积 减少文件数量 提高网页加载速度 4 webpack工作流程 1 初始化参数 从配
  • 一个人再牛,最终还是要靠团队

    软件行业个人英雄主义时代已经渐渐远去 在CS以及自由软件盛行的年代 确实造就了许多的软件英雄 如今的互联网 时代 我们只能去怀念他们 无论是创业还是软件平台的研发与运营 我们都在强调着团队 马云再牛 没有十八罗汉 他也只不过是一个到处吹牛到
  • 报错解决TypeError: write() argument must be str, not list

    今天写爬虫的时候遇到的问题 将抓取的数据保存下来的时候报错 TypeError write argument must be str not list 字面意思是write写入的应该是str类型的数据 而不是一个list类型的数据 回到代码
  • x264的参考帧管理机制

    x264介绍 X264是一款研究的是H 264编码的开源代码软件 相比JM而言 其编码性能有很大的提高 其支持大多数H 264的特性工具 包括 CABAC和 CAVLC高效嫡编码 多参考帧预测 所有的帧内预测宏块类型 16x6l和4x4 所
  • 官宣——BSV工程师能力认证项目在CSDN推出线上学习平台

    去年11月 上海可一澈科技有限公司 以下简称 可一科技 与CSDN联合推出了BSV区块链开发工程师能力认证项目 以下简称 BSV工程师认证 今天 BSV工程师认证项目正式推出一个全新的线上学习平台 并发布首门课程 比特币协议与设计 本次推出
  • LDO基础知识:噪声 - 降噪引脚如何提高系统性能

    使用低压降稳压器 LDO 来过滤开关模式电源产生的纹波电压并不是实现清洁直流电源的唯一考虑因素 由于 LDO 是电子器件 因此它们会自行产生一定量的噪声 选择低噪声 LDO 并采取措施来降低内部噪声对于生成不会影响系统性能的清洁电源轨而言不
  • PYQT的最新界面代码

    This Python file uses the following encoding utf 8 import sqlite3 import traceback from PyQt5 QtGui import QMouseEvent Q
  • springboot入门简单使用

    springboot入门简单使用 1 SpringBoot项目创建并配置mysql数据库 创建项目 编写Controller测试 配置数据库 2 SpringBoot集成mybatis plus 初始化数据库 安装mybatis plus