美文网首页
SpringBoot + MyBatis 创建一个新项目

SpringBoot + MyBatis 创建一个新项目

作者: ChenME | 来源:发表于2018-12-04 13:47 被阅读25次

    作为一个做移动端的 coder,偶尔做一次后台项目,总是卡在项目的初始化上面,所以我觉得有必要做一个记录,方便下次初始化项目时使用。


    文章用到的一些 MyBatis 的配置内容,详细参照《有关 MyBatis 的配置详解》


    1. 创建项目,过程简单,图片代替:

    创建项目1.png 创建项目2.png 创建项目3.png 创建项目4.png

    得到项目的 package:mm.cme.xxxos

    2. 添加常用的依赖:

    1. c3p0 数据库连接池;
    <dependencies>
      <!-- 数据库连接池 -->
      <dependency>
          <groupId>com.mchange</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.5.2</version>
      </dependency>
    </dependencies>
    
    1. 由于项目中的 JavaBean 用到了 Kotlin 的 date class,所以依赖了 Kotlin 相关的内容(其实这个也不必手动添加,直接在项目中编写 Kotlin 代码,IDEA 会自动识别并提醒添加依赖的);
    <dependencies>
      <!-- Kotlin -->
      <dependency>
          <groupId>org.jetbrains.kotlin</groupId>
          <artifactId>kotlin-stdlib-jdk8</artifactId>
          <version>${kotlin.version}</version>
      </dependency>
      <dependency>
          <groupId>org.jetbrains.kotlin</groupId>
          <artifactId>kotlin-test</artifactId>
          <version>${kotlin.version}</version>
          <scope>test</scope>
      </dependency>
    </dependencies>
    

    注意需要在配置中添加 Kotlin 的版本;

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <kotlin.version>1.2.71</kotlin.version>
    </properties>
    

    3. SpringBoot 的配置文件,这里用了 yml 文件(application.yml);

    server:
      port: 8082
      servlet:
        context-path: /xxxos # 配置项目的路由
    

    主要是配置端口以及项目的路由;

    4. 配置数据库 重点

    1. resource 下创建 mybatis 的配置文件 mybatis-config.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        <!-- 配置全局属性 -->
        <settings>
            <!-- 使用 jdbc 的 getGeneratedKeys 获取数据库自增的主键值
            (当 insert 时,会返回数据库自增的主键值,如果传入的是实体类,它会自动向实体类的主键赋值)-->
            <setting name="useGeneratedKeys" value="true"/>
    
            <!-- 使用列标签替换列别名 -->
            <setting name="useColumnLabel" value="true"/>
    
            <!-- 开启驼峰命名转换 Table{user_name} -> Bean{userName} -->
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        </settings>
    </configuration>
    

    重点是 useGeneratedKeys,当 insert 时,会返回数据库自增的主键值,如果传入的是实体类,它会自动向实体类的主键赋值

    1. 配置 DataSource
    • application.yml 文件中添加数据库的连接信息:
    jdbc:
      driver: com.mysql.cj.jdbc.Driver  # driver: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/xxxos
      user: root
      pwd: root
    
    • 创建 package config.dao
    • 在该 package 下面创建一个 class:DataSourceConfiguration.java
    @Configuration
    @MapperScan("mm.cme.xxxos.dao") // 配置 mybatis mapper 的扫描路径
    public class DataSourceConfiguration {
    
        @Value("${jdbc.driver}")
        private String driverClass;
        @Value("${jdbc.url}")
        private String jdbcUrl;
        @Value("${jdbc.user}")
        private String jdbcUser;
        @Value("${jdbc.pwd}")
        private String jdbcPwd;
    
        @Bean(name = "dataSource")
        public ComboPooledDataSource createDataSource() throws PropertyVetoException {
    
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(driverClass);
            dataSource.setJdbcUrl(jdbcUrl);
            dataSource.setUser(jdbcUser);
            dataSource.setPassword(jdbcPwd);
    
            //关闭连接后不自动 commit,便于事务控制
            dataSource.setAutoCommitOnClose(false);
    
            return dataSource;
        }
    }
    
    1. 配置 SessionFactory
    • resource 下面创建 dir:mapper,用于后面存放 mybatis 的 mapper 文件使用;
    • application.yml 文件中添加 session 相关的控制信息:
    mybatis_config_file: mybatis-config.xml
    mapper_path: /mapper/**.xml
    bean_package: mm.cme.xxxos.dao
    
    • 在该 config.dao 下面创建一个 class:SessionFactoryConfiguration.java
    @Configuration
    public class SessionFactoryConfiguration {
    
        // mybatis-config.xml 配置文件的路径
        @Value("${mybatis_config_file}")
        private String mybatisConfigFilePath;
    
        // mybatis mapper 文件所在路径
        @Value("${mapper_path}")
        private String mapperPath;
    
        // 实体类所在的 package
        @Value("${bean_package}")
        private String beanPackage;
    
        @Autowired
        @Qualifier("dataSource") // 加载 DataSourceConfiguration 中的 ComboPooledDataSource
        private DataSource dataSource;
    
        @Bean("sqlSessionFactory")
        public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFilePath));
    
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            String packageSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
            sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packageSearchPath));
    
            sqlSessionFactoryBean.setDataSource(dataSource);
            sqlSessionFactoryBean.setTypeAliasesPackage(beanPackage);
    
            return sqlSessionFactoryBean;
        }
    }
    
    1. 配置事务管理(开启事务管理):
    • 创建 package:config.service
    • 在该目录下创建 class:TransactionManagementConfig.java
    @Configuration
    @EnableTransactionManagement // 开启事务的管理
    public class TransactionManagementConfig implements TransactionManagementConfigurer{
    
        @Autowired
        private DataSource dataSource;
    
        @Override
        public PlatformTransactionManager annotationDrivenTransactionManager() {
            return new DataSourceTransactionManager(dataSource);
        }
    }
    

    5. 创建数据表,准备编码测试:

    1. 启动 MySql,并创建数据库 xxxos
    2. xxxos 中创建一个 goods_color 表并插入数据;
    -- ----------------------------
    -- Table structure for goods_color
    -- ----------------------------
    DROP TABLE IF EXISTS `goods_color`;
    CREATE TABLE `goods_color` (
      `color_id` int(11) NOT NULL AUTO_INCREMENT,
      `color_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '颜色名字',
      `color_description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '描述',
      `color_remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '备注',
      PRIMARY KEY (`color_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of goods_color
    -- ----------------------------
    BEGIN;
    INSERT INTO `goods_color` VALUES (1, '杂色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (2, '黑色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (3, '白色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (4, '红色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (5, '米色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (6, '灰色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (7, '黄色', NULL, NULL);
    INSERT INTO `goods_color` VALUES (9, '蓝色', NULL, NULL);
    COMMIT;
    

    6. 编码:

    1. 在编码前,先完善项目的目录结构
    mm.cme.xxxos
      |-- base
      |-- bean (存放 JavaBean)
      |-- comm (存放一些公共的 class)
      |-- config (存放配置文件)
        |-- dao
        |-- service
      |-- constant (存放常量)
      |-- controller
      |-- dao
      |-- domain (存放请求的参数的 JavaBean)
      |-- handler (存放一些处理的 class,例如异常处理等)
      |-- service
        |-- impl
      |-- utils
    
    1. 编写 Const:
    • comm 目录下创建:
    public interface Const {
        String Default_Chartest = "UTF-8";
        String Default_JsonContentType = "application/json;charset=UTF-8";
    }
    
    1. 编写 ResultCode:
    • constant 目录下创建:
    enum class ResultCode(val code: Int, val message: String) {
        Error(-1, "网络请求错误"),
        ErrDataEmpty(1000, "数据为空"),
        Success(0, "成功")
    }
    
    1. 编写 BaseController:
    • base 目录下创建:
    public class BaseController {
    
        /**
         * 将得到的 list 集合处理并返回
         *
         * @param list
         * @param <T>
         * @return
         */
        protected <T> BaseResp<Map<String, Object>> handleListResult(List<T> list) {
    
            BaseResp<Map<String, Object>> resp = new BaseResp<>();
            Map<String, Object> map = new HashMap<>();
    
            if (null == list || list.size() <= 0) {
                resp.setStatus(ResultCode.ErrDataEmpty.getCode());
                resp.setMsg(ResultCode.ErrDataEmpty.getMessage());
            } else {
                map.put("list", list);
                resp.setData(map);
            }
            return resp;
        }
    
        /**
         * 将得到的 map 集合处理并返回
         *
         * @param map
         * @return
         */
        protected BaseResp<Map<String, Object>> handleMapResult(Map<String, Object> map) {
    
            BaseResp<Map<String, Object>> resp = new BaseResp<>();
            resp.setData(map);
            return resp;
        }
    
        /**
         * 将得到的 bean 处理并返回
         *
         * @param bean
         * @param <T>
         * @return
         */
        protected <T> BaseResp<T> handleBeanResult(T bean) {
    
            BaseResp<T> resp = new BaseResp<>();
    
            if (null == bean) {
                resp.setStatus(ResultCode.Error.getCode());
                resp.setMsg(ResultCode.Error.getMessage());
            } else {
                resp.setData(bean);
            }
            return resp;
        }
    
        /**
         * 将得到的 bool 处理并返回
         *
         * @param isSuccess
         * @return
         */
        protected BaseResp handleSuccess(boolean isSuccess) {
    
            BaseResp resp = new BaseResp();
    
            if (!isSuccess) {
                resp.setStatus(ResultCode.Error.getCode());
                resp.setMsg(ResultCode.Error.getMessage());
            }
            return resp;
        }
    }
    
    1. 编写 BaseResp:
    • bean 目录下创建:
    class BaseResp<T>(var status: Int = ResultCode.Success.code,
                      var msg: String = ResultCode.Success.message,
                      var data: T? = null) : Serializable
    
    1. 编写 JavaBean:
    • bean 目录下创建:
    data class ColorBean(
            val colorId: Int = 0,
            val colorName: String,
            val colorDescription: String?,
            val colorRemark: String?
    )
    
    1. 编写 Dao:
    • dao 目录下创建:
    interface ColorDao {
    
        /**
         * 获取商品的所有颜色
         */
        fun listAllColor(): List<ColorBean>
    
        /**
         * 更新颜色
         */
        fun updateColor(bean: ColorBean): Int
    
        /**
         * 新增一个颜色
         */
        fun addColor(bean: ColorBean): Int
    }
    
    1. 编写 mapper:
    • resource/mapper 目录下创建:
    <?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="mm.cme.xxxos.dao.ColorDao">
        <select id="listAllColor" resultType="mm.cme.xxxos.bean.ColorBean">
            SELECT * FROM goods_color;
        </select>
    
        <update id="updateColor" parameterType="mm.cme.xxxos.bean.ColorBean">
            UPDATE goods_color
            <set>
                <if test="null!=colorName">color_name = #{colorName},</if>
                <if test="null!=colorDescription">color_description = #{colorDescription},</if>
                <if test="null!=colorRemark">color_remark = #{colorRemark},</if>
            </set>
            WHERE color_id = #{colorId};
        </update>
    
        <insert id="addColor" useGeneratedKeys="true" keyColumn="color_id" keyProperty="colorId"
                parameterType="mm.cme.xxxos.bean.ColorBean">
            INSERT INTO
            goods_color(color_name, color_description, color_remark)
            VALUES (#{colorName}, #{colorDescription}, #{colorRemark});
        </insert>
    </mapper>
    
    1. 编写 Service:
    • service 目录下创建:
    interface ColorService {
    
        /**
         * 获取商品的所有颜色
         */
        fun listAllColor(): List<ColorBean>
    
        /**
         * 更新颜色
         */
        fun updateColor(bean: ColorBean): Boolean
    
    
        /**
         * 新增一个颜色
         */
        fun addColor(bean: ColorBean): ColorBean
    }
    
    1. 编写 ServiceImpl:
    • service/impl 目录下创建:
    @Service
    public class ColorServiceImpl implements ColorService {
    
        @Autowired
        ColorDao colorDao;
    
        @NotNull
        @Override
        public List<ColorBean> listAllColor() {
            return colorDao.listAllColor();
        }
    
        @Transactional
        @Override
        public boolean updateColor(@NotNull ColorBean bean) {
            try {
                if (colorDao.updateColor(bean) > 0) {
                    return true;
                } else {
                    throw new RuntimeException("颜色信息更新失败!");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("颜色信息更新失败!");
            }
        }
    
        @Transactional
        @NotNull
        @Override
        public ColorBean addColor(@NotNull ColorBean bean) {
            try {
                if (colorDao.addColor(bean) > 0) {
                    return bean;
                } else {
                    throw new RuntimeException("新增颜色失败!");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("新增颜色失败!");
            }
        }
    }
    
    1. 编写 Controller:
    • controller 目录下创建:
    @RestController
    @RequestMapping(produces = {Const.Default_JsonContentType}, value = {"/color"})
    public class ColorController extends BaseController {
    
        @Autowired
        ColorService mService;
    
        /**
         * 获取商品的所有颜色
         *
         * @return
         */
        @GetMapping("/listAllColor")
        public BaseResp<Map<String, Object>> listAllColor() {
            return handleListResult(mService.listAllColor());
        }
    
        /**
         * 更新颜色
         *
         * @return
         */
        @PostMapping("/updateColor")
        public BaseResp updateColor(@RequestBody ColorBean req) {
            return handleSuccess(mService.updateColor(req));
        }
    
        /**
         * 新增一个颜色
         *
         * @param bean
         * @return
         */
        @PostMapping("/addColor")
        public BaseResp<ColorBean> addColor(@RequestBody ColorBean bean) {
            return handleBeanResult(mService.addColor(bean));
        }
    }
    
    1. 统一异常处理:
    • handler 目录下创建:
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public BaseResp<HashMap<String, Object>> exceptionHandler(HttpServletRequest req, Exception e) throws Exception {
            BaseResp<HashMap<String, Object>> resp = new BaseResp<>();
            resp.setStatus(ResultCode.Error.getCode());
            resp.setMsg(e.getMessage());
            return resp;
        }
    }
    

    7. 运行测试:

    1. listAllColor
    // url
    http://localhost:8082/xxxos/color/listAllColor
    
    // resp (部分)
    {
        "status": 0,
        "msg": "成功",
        "data": {
            "list": [
                {
                    "colorId": 1,
                    "colorName": "杂色",
                    "colorDescription": null,
                    "colorRemark": null
                },
                {
                    "colorId": 2,
                    "colorName": "黑色",
                    "colorDescription": null,
                    "colorRemark": null
                }
            ]
        }
    }
    
    1. addColor
    // url
    http://localhost:8082/xxxos/color/addColor
    
    // param
    {
        "colorName":"无色",
        "colorDescription":"就是这么任性",
        "colorRemark":"就是这么任性"
    }
    
    // resp
    {
        "status": 0,
        "msg": "成功",
        "data": {
            "colorId": 10,
            "colorName": "无色",
            "colorDescription": "就是这么任性",
            "colorRemark": "就是这么任性"
        }
    }
    
    1. updateColor
    // url
    http://localhost:8082/xxxos/color/updateColor
    
    // param
    {
        "colorId":10,
        "colorName":"无色透明",
        "colorDescription":"皇帝的新衣",
        "colorRemark":"皇帝的新衣"
    }
    
    // resp
    {
        "status": 0,
        "msg": "成功",
        "data": null
    }
    

    相关文章

      网友评论

          本文标题:SpringBoot + MyBatis 创建一个新项目

          本文链接:https://www.haomeiwen.com/subject/utfmcqtx.html