3、整合MyBatis操作
starter
SpringBoot官方的Starter:spring-boot-starter-*
*第三方的: -spring-boot-starter MyBatis属于第三方…
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency>
1、配置模式
之前我们使用Mybatis的方式:
编写全局配置文件—>SqlMapConfig.xml
创建SqlSessionFactory:
获取SqlSession
编写Mapper接口.
现在所有的配置都在MybatisAutoConfiguration中.
SqlSessionFactory在MybatisAutoConfiguration自动配置好了.也自动配置了 SqlSessionTemplate,内部 组合了SqlSession.
AutoConfiguredMapperScannerRegistrar:处理我们的Mapper, 只要我们写的操作MyBatis的接口标注了 @Mapper 就会被自动扫描进来
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })//这些都是Mybatis中的,当导入Mybatis依赖后才会生效. @ConditionalOnSingleCandidate(DataSource.class) //使用咱们Druid的 @EnableConfigurationProperties(MybatisProperties.class) //Mybatis配置项绑定类 @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class }) public class MybatisAutoConfiguration implements InitializingBean { @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {...} @Bean @ConditionalOnMissingBean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {...} public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar { ... } }
- MyBatis的所有配置项都以mybatis开头,全局配置都以mybatis.configuration.XXX开头.
测试代码:
#########################################Account###################################### @Data public class Account { private Long id; private String userId; private Integer money; } ###########################################IndexController########################### @Slf4j @Controller public class IndexController { @Autowired AccountService accountService; @ResponseBody @GetMapping("/acct") public Account getById(@RequestParam("id") Long id){ return accountService.getAcctById(id); } } ##############################AccountService#################################### public interface AccountService { public Account getAcctById(Long id); } @Service public class AccountServiceImpl implements AccountService { @Autowired AccountMapper accountMapper; @Override public Account getAcctById(Long id) { return accountMapper.getAcct(id); } }
配置文件:
####################################AccountMapper.xml################################ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.rg.admin.mapper.AccountMapper"> <select id="getAcct" resultType="com.rg.admin.bean.Account"> select * from account where id = #{id} </select> </mapper> ###########################################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>--> <!-- <setting name="mapUnderscoreToCamelCase" value="true"/>--> <!--</settings>--> <!--开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。--> </configuration> #################################application.yaml################################ spring: datasource: url: jdbc:mysql:///test username: root password: 186259 driver-class-name: com.mysql.jdbc.Driver mybatis: # config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置 mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件位置 configuration: map-underscore-to-camel-case: true # 开启驼峰命名自动映射(在数据库中映射为_) # 可以不写全局配置文件;所有全局配置文件的配置都放在configuration配置项中即可
注:配置mybatis.configuration下面的所有,就是相当于改mybatis全局配置文件中的值
SpringBoot整合MyBatis开发步骤总结:
导入mybatis官方starter
编写mapper接口。标准@Mapper注解
编写sql映射文件并绑定mapper接口
在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息 (建议;配置在mybatis.configuration)
2、注解模式 及混合模式
@Mapper public interface CityMapper { @Select("select * from city where id = #{id}") public City getById(Long id); // @Insert("insert into city(`name`,`state`,`country`) values(#{name},#{state},#{country})") // @Options(useGeneratedKeys = true,keyProperty = "id") // MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键并封装到city中 public void saveCity(City city); }
<?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="com.atguigu.admin.mapper.CityMapper"> public void insert(City city); <insert id="insert" useGeneratedKeys="true" keyProperty="id"> insert into city(`name`,`state`,`country`) values(#{name},#{state},#{country}) </insert> </mapper>
最佳实战:
引入mybatis-starter
配置application.yaml中,指定mapper-location位置即可
编写Mapper接口并标注@Mapper注解
简单方法直接注解方式
复杂方法编写mapper.xml进行绑定映射
*@MapperScan(“com.atguigu.admin.mapper”) *简化,其他的接口就可以不用标注@Mapper注解
4、整合 MyBatis-Plus 完成CRUD
1、什么是MyBatis-Plus
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis plus 官网
建议安装 MybatisX 插件
2、整合MyBatis-Plus
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> 里面包含着MybatisPlusAutoConfiguration ,Mybatis核心包,jdbc操作数据库的包,mybatis-spring整合包.
自动配置
MybatisPlusAutoConfiguration 配置类,与MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制
SqlSessionFactory 自动配置好。底层是容器中默认的数据源
mapperLocations 自动配置好的。有默认值–>classpath*:/mapper/**/*.xml;任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件,放在 mapper下
容器中也自动配置好了 SqlSessionTemplate
@Mapper 标注的接口也会被自动扫描;建议直接 @MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行
优点:
只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力
3、CRUD功能测试
#########################################UserMapper############################### //UserMapper public interface UserMapper extends BaseMapper<User> { } ####################################UserService####################################### public interface UserService extends IService<User> {//T:定义要操作的数据表的实体. } @Service //ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> M要操作的Mapper类,T:对应的实体. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { } ###############################controller############################################# //表格数据显示 @GetMapping("/dynamic_table") public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model){ //分页查询数据 Page <User> userPage = new Page <>(pn, 2); Page <User> page = userService.page(userPage, null);//分页查询结果. //long pages = page.getPages(); // long current = page.getCurrent(); // List <User> records = page.getRecords(); model.addAttribute("page", page); return "table/dynamic_table"; } //删除用户逻辑 @GetMapping("/user/delete/{id}") public String deleteUser(@PathVariable("id") Long id, @RequestParam(value = "pn",defaultValue = "1") Integer pn, RedirectAttributes ra){//RedirectAttributes 重定向携带的数据. userService.removeById(id); ra.addAttribute("pn", pn);// 会拼在转发路径后面.. return "redirect:/dynamic_table"; } //
静态页面dynamic_table.html
<div class="panel-body"> <div class="adv-table"> <table class="display table table-bordered" id="hidden-table-info"> <thead> <tr> <th>#</th> <th>id</th> <th>name</th> <th>age</th> <th>email</th> <th>操作</th> </tr> </thead> <tbody> <!-- 表格数据显示 --> <tr class="gradeX" th:each="user,status:${page.records}"> <td th:text="${status.count}">Trident</td> <td th:text="${user.id}"></td> <td th:text="${user.name}">Win 95+</td> <td th:text="${user.age}">4</td> <td>[[${user.email}]]</td> <td> <!-- 点击删除当前记录,并返回本页. --> <a th:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}" class="btn btn-danger btn-sm" type="button">删除</a> </td> </tr> </tbody> </table> <!-- 分页代码 --> <div class="row-fluid"> <div class="span6"> <div class="dataTables_info" id="hidden-table-info_info">当前 第 [[${page.current}]] 页 总计 [[${page.pages}]] 页 共 [[${page.total}]] 记录 </div> </div> <div class="span6"> <div class="dataTables_paginate paging_bootstrap pagination"> <ul> <li class="prev disabled"><a href="#">← Previous</a></li> <!-- 单击之后跳转到指定页 --> <li th:class="${num == page.current ? 'active' :'' }" th:each="num:${#numbers.sequence(1,page.pages)}"> <a th:href="@{/dynamic_table(pn=${num})}" >[[${num}]]</a> </li> <li class="next"><a href="#">Next → </a></li> </ul> </div> </div> </div> </div> </div>
效果展示:
2、NoSQL
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
1、Redis自动配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
自动配置:
RedisAutoConfiguration 自动配置类。RedisProperties 属性类 --> spring.redis.xxx是对redis的配置
连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration
自动注入了RedisTemplate<Object, Object> : xxxTemplate都是工具类;
自动注入了StringRedisTemplate;k:v都是String
底层只要我们使用 StringRedisTemplate、RedisTemplate就可以操作redis
redis环境搭建
1、阿里云按量付费redis。经典网络
2、申请redis的公网连接地址
3、修改白名单 允许0.0.0.0/0 访问
有个默认账号,当然也可以申请多个账号.
使用完后要记得释放下…
2、RedisTemplate与Lettuce
@Test void testRedis(){ ValueOperations<String, String> operations = redisTemplate.opsForValue(); operations.set("hello","world"); String hello = operations.get("hello"); System.out.println(hello); }
3、切换至jedis
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 导入jedis客户端操作redis(因为默认还有Lettuce也可以进行操作.)--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> spring: redis: # redis://user:password@example.com:6379 url: redis://lxy:Lxy123456@r-bp1r5uws0tty3chbv7pd.redis.rds.aliyuncs.com:6379 jedis: pool: max-active: 10 # 最大活跃数
案例:显示main.html以及sql的访问次数到main页面.
#################################Interceptor######################################## @Component public class RedisUrlCountInterceptor implements HandlerInterceptor { @Autowired StringRedisTemplate redisTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); //默认每次访问当前uri就会计数+1 redisTemplate.opsForValue().increment(uri); return true; } } #######################################WebMvcConfigurer############################ @Configuration public class AdminWebConfig implements WebMvcConfigurer { /** * Filter、Interceptor 几乎拥有相同的功能? * 1、Filter是Servlet定义的原生组件。好处,脱离Spring应用也能使用 * 2、Interceptor是Spring定义的接口。可以使用Spring的自动装配等功能 * */ @Autowired RedisUrlCountInterceptor redisUrlCountInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) //登录注册拦截器 .addPathPatterns("/**")// 所有的请求都被拦截器拦截,包括静态资源 /**中 * 单级目录,/**代表多级目录.不能直接使用/*/* .excludePathPatterns("/", "/login","/error", "/css/**", "/fonts/**", "/images/**", "/js/**");//放行的请求. //这里一定要使用注入的,使用new 的,里面的东西都为空... registry.addInterceptor(redisUrlCountInterceptor).addPathPatterns("/**") .excludePathPatterns("/", "/login","/error", "/css/**", "/fonts/**", "/images/**", "/js/**"); } } ################################Controller########################################## @Slf4j @Controller public class IndexController { @GetMapping("/main.html") public String mainPage(HttpSession session,Model model){ log.info("当前方法是:{}","mainPage"); // // 是否登录 拦截器,过滤器 // Object loginUser = session.getAttribute("loginUser"); // if(loginUser!=null){ // return "main"; // }else{ // //回到登录页面 // model.addAttribute("msg","请重新登录"); // return "login"; // } ValueOperations <String, String> operations = redisTemplate.opsForValue(); String s = operations.get("/main.html"); String s1 = operations.get("/sql"); model.addAttribute("mainCount", s); model.addAttribute("sqlCount", s1); return "main"; //这中间的所有拦截操作,可以交给拦截器来搞. } } ###########################main.html############################################### <div class="col-xs-8"> <span class="state-title" th:text="${mainCount}"> New Order </span> <h4>\main.html</h4> </div> <div class="col-xs-8"> <span class="state-title" th:text="${sqlCount}"> Unique Visitors </span> <h4>/sql</h4> </div>
运行结果: