美文网首页technology-integration全面解析
technology-integration(四)---Spri

technology-integration(四)---Spri

作者: 海苔胖胖 | 来源:发表于2018-08-23 15:26 被阅读660次

    Mybatis

    Mybatis作为本人最喜欢的持久层框架,当然得整合进来啦!!!

    • Mybatis需要程序猿自己编写增删改查所需要的SQL语句,而Hibernate可以通过对象关系模型实现对数据库的操作,可以完全脱离SQL,但正因如此Mybatis可以根据业务最大程度优化SQL语句来达到良好的性能。Mybatis也有第三方工具提供类似Hibernate的功能,比如Mybatis-plus,这里暂时不介绍
    • Mybatis的可移植性非常一般...虽说有支持,但局限性还是比较大的,而Hibernate所使用的HQL则可以转换成对应数据库的SQL。虽说好像很厉害,但一般来说换数据库的操作还是比较少的。
    • 还有其他区别,但我就不写

    SpringBoot整合Mybatis

    添加jar依赖---pom.xml
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
    </dependency>
    

    导入Mybatis相关依赖,mybatis-spring-boot-starter是把Mybatis.jar和mybatis-spring.jar整合在了一起。

    配置Mybatis

    配置Mybatis常用两种方式,一种使用SpringBoot配置文件方式配置数据库连接及Mybatis;另一种则是使用java config配置(代码方式),这也是我比较喜欢的一种方式。

    application.yml方式

    1、在application.yml配置数据库连接信息及Mybatis

    spring:
      datasource:
          data-source-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/technology-integration
          username: root
          password: 123456
    
    mybatis:
      mapper-locations: classpath:mapping/ *.xml
      type-aliases-package: com.viu.technology.po 
    
    

    2、在TechnologyIntegrationApplication.class中添加MapperScan注解,该注解用于扫描Mapper接口所在的包

    @SpringBootApplication
    @MapperScan("com.viu.technology.mapper")
    public class TechnologyIntegrationApplication implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(TechnologyIntegrationApplication.class, args);
        }
    }
    
    
    java config方式

    在config.datasource包中创建MybatisConfig类

    
    @Configuration
    @MapperScan("com.viu.technology.mapper") 
    public class MybatisConfig extends HikariConfig{
    
        @Autowired
        private Environment env;
    
        @Bean
        @Primary
        @ConfigurationProperties(prefix = "datasource1.jdbc")
        public DataSource dataSource() {
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setDriverClassName(env.getProperty("datasource1.jdbc.driverClassName"));
            dataSource.setJdbcUrl(env.getProperty("datasource1.jdbc.url"));
            dataSource.setUsername(env.getProperty("datasource1.jdbc.username"));
            dataSource.setPassword(env.getProperty("datasource1.jdbc.password"));
            dataSource.setMaximumPoolSize(100);
            dataSource.setPoolName("hikari-");
            return dataSource;
        }
    
        @Bean
        @Primary
        public SqlSessionFactory sqlSessionFactory( DataSource dataSource) throws Exception {
            SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
            fb.setDataSource(dataSource);
            fb.setTypeAliasesPackage("com.viu.technology.po");
            fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/*.xml"));
            return fb.getObject();
        }
    }
    

    application.yml

    datasource1.jdbc:
      driverClassName: com.mysql.jdbc.Driver
      jdbcUrl: jdbc:mysql://localhost:3306/technology-integration
      username: root
      password: 123456
      min-idle: 10
    
    • @MapperScan("com.viu.technology.mapper") :扫描Mapper接口所在的包
    • @Primary :在拥有多个同类型Bean时,SpringBoot自动注入会选择带有该注解的Bean,否则自动注入将会提示注入失败,原因是因为IOC中拥有多个同类型的Bean,而SpringBoot无法判断使用哪个Bean,导致异常发生。
    • Environment:可获取到所有的配置资源
    • @ConfigurationProperties(prefix = "datasource1.jdbc") :加载application..yml以datasource1.jdbc开头的配置
    • fb.setTypeAliasesPackage("com.viu.technology.po"):设置该包下的所有类可以在mapper.xml中直接使用类名而非全类名

    这里需要使用@Primary注解是因为SpringBoot默认配置了SqlSessionFactory和DataSource,即SpringBoot的IOC容器启动时会自动将这两个Bean注入进来,而我们选择java config方式配置数据库时则会与SpringBoot默认配置的DataSource Bean产生冲突,@Primary注解则是用来告诉容器优先选择java config配置的Bean。不过该方式并不是最好的解决方案,因为SpringBoot默认配置的DataSource Bean我们并没有使用,我们可以在启动类中取消SpringBoot自动配置的DataSource,这样就不需要加@Primary注解,还能提高应用的启动速度。

    @SpringBootApplication
    @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
    public class TechnologyIntegrationApplication implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(TechnologyIntegrationApplication.class, args);
        }
    }
    



    SpringBoot配置Mybatis就完成了,接下来写个注册用户的案例



    步骤:

    1. 创建一条新的用户数据,userId使用Mybatis生成UUID进行插入,并返回
    2. 创建一条新的用户角色数据,简单业务,ID自增
    3. 创建成功并返回

    编写SQL语句

    UserMapper.xml

    selectKey 会将MySQL select的结果放入到传入的model的主键里面,
    keyProperty 对应的model中的主键的属性名,这里是 user 中的id,因为它跟数据库的主键对应
    order AFTER 表示 SELECT在insert执行之后执行,多用与自增主键;
    BEFORE 表示 SELECT在insert执行之前执行, 这种适合那种主键不是自增的类型

    <insert id="insert" parameterType="com.viu.technology.po.User">
        <selectKey keyProperty="id" resultType="string" order="BEFORE">
          select replace(uuid(), '-', '') as id from dual
        </selectKey>
        insert into t_user (id,name, phone,password)
        values (#{id},#{name}, #{phone}, #{password}
          )
      </insert>
    

    RoleMapper.xml

    <insert id="insert" parameterType="com.viu.technology.po.Role">
        insert into t_role (role_name, user_id)
        values ( #{roleName,jdbcType=VARCHAR}, #{userId,jdbcType=INTEGER})
      </insert>
    

    编写DAO类

    在项目的dao包创建UserDao接口类

    public interface UserDao {
        User selectByPrimaryKey(String id);
    }
    
    @Repository
    public class UserDaoImpl implements UserDao{
        @Autowired
        private UserMapper userMapper;
    
        public User selectByPrimaryKey(String id) {
            return userMapper.selectByPrimaryKey(id);
        }
    }
    
    public interface RoleDao {
        Role insertRole(Role role);
    }
    
    @Repository
    public class RoleDaoImpl implements RoleDao {
        @Autowired
        private RoleMapper roleMapper;
    
        @Override
        public Role insertRole(Role role) {
            if (roleMapper.insert(role)>0) {
                return role;
            }
            return null;
        }
    }
    

    UserDao的实现类需要加入@Repository,一是为了把该类注册为Bean,二是该注解支持处理数据库操作产生的异常

    编写Service类

    public interface UserService {
        User registerUser(User user);
    }
    
    
    @Service
    public class UserServiceImpl implements UserService{
        @Autowired
        private UserDao userDao;
    
        @Transactional
        @Override
        public User registerUser(User user) {
            User userRes = userDao.insertUser(user);
            Role roleRes = roleDao.insertRole(new Role("普通群众", user.getId()));
            List list = new ArrayList();
            list.add(roleRes);
    
            if (null != userRes && null != roleRes) {
                userRes.setRoles(list);
                return user;
            }
            return null;
        }
    }
    

    编写Result类(用于统一返回结果)

    public class Result<T> {
    
        private String code;
        private String msg;
        private T data;
    
        public Result() {}
    
        public Result(ResultCode resultCode, T data) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
            this.data = data;
        }
    
        public Result(ResultCode resultCode) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
        }
    
        public static Result success() {return new Result(ResultCode.SUCCESS);}
        public static Result success(Object data) {return new Result(ResultCode.SUCCESS, data); }
        public static Result fail(ResultCode resultCode,String msg){return new Result(resultCode, msg);}
        public static Result fail(ResultCode resultCode){return new Result(resultCode);}
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
    public class ResultCode {
    
        private String code;
    
        private String msg;
    
        public static ResultCode SUCCESS = new ResultCode("0000", "success");
        public static ResultCode DATA_CHECK_FAILURE = new ResultCode("1000", "数据校验失败");
        public static ResultCode DATA_INSERT_FAILURE = new ResultCode("1001", "数据插入失败");
        public static ResultCode SECKILL_END = new ResultCode("2001", "秒杀结束");
        public static ResultCode SMS_SEND_FAIL = new ResultCode("3001", "短信发送失败");
        public static ResultCode SMS_CODE_VALID_FAIL = new ResultCode("3002", "短信校验失败");
        public static ResultCode SMS_QUERY_NOT_FOUND = new ResultCode("3003", "找不到该短信");
        public static ResultCode USER_REGISTER_FIAL = new ResultCode("4000", "用户注册失败");
        public static ResultCode USER_LOGIN_FIAL = new ResultCode("401", "用户身份验证失败");
        public static ResultCode USER_PERMISSION_DENIED = new ResultCode("403", "用户账号权限不足");
    
        public ResultCode(String code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public String getCode() {return code;}
    
        public void setCode(String code) {this.code = code;}
    
        public String getMsg() {return msg;}
    
        public void setMsg(String msg) {this.msg = msg;}
    }
    

    编写Controller类

    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Autowired
        private UserServiceImpl userService;
    
        @PostMapping("/register")
        public Result insertUser(@RequestBody User user) {
            User result = userService.registerUser(user);
            if (null != result) {
                return Result.success(result);
            }
            return Result.fail(ResultCode.USER_REGISTER_FIAL);
        }
    }
    

    测试

    启动SpringBoot应用,在postman中测试该地址


    image.png

    更多文章请关注该 technology-integration全面解析专题

    相关文章

      网友评论

        本文标题:technology-integration(四)---Spri

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