springBoot基础(一)

本文详细介绍了如何在Spring Boot项目中集成JPA和MyBatis,包括数据库连接配置、实体类、DAO接口、Controller层的实现,以及分页查询的处理。还探讨了使用PageHelper分页插件在MyBatis中的应用,并展示了SQLite数据库的配置和使用。
摘要由CSDN通过智能技术生成


前言

这是学习springBoot初期的学习笔记。。。欢迎各位大佬指正!!!

创建idea集成的springBoot项目

第一步:直接创建就ok,如下:
在这里插入图片描述
然后下一步;最终会形成一个这样的目录结构:
在这里插入图片描述

在springBoot中使用jsp

第一步添加依赖:
在pom.xml中,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.drillsb</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot</name>
    <packaging>war</packaging>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
<!--        Servlet的依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

<!--        tomcat的支持-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <directory>src/main/webapp</directory>
                <targetPath>META-INF/resources</targetPath>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

注意点:

也就是添加三个依赖,如下:

<!--        Servlet的依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

<!--        tomcat的支持-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
注意了,必须要指明资源的路径,也就是在pom.xml中添加资源的路径,如下:
<!--        资源路径-->
        <resources>
            <resource>
                <directory>src/main/webapp</directory>
                <targetPath>META-INF/resources</targetPath>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
除此之外,跟原来的web项目一样,也要指定资源路径,如下:

在这里插入图片描述
然后就形成了,这样的目录结构,如下:
在这里插入图片描述
这样就真正的实现了在springboot中使用jsp;

在spring中启动热部署

在pom.xml中添加一个插件和一个依赖即可,如下:

<!--        添加热部署,其中optional为true才能生效-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

这样在idea中还是实现不了热部署的。。。。因为在idea中默认情况下是不会进行热部署,所以要设置几步;
首先,打开idea的setting设置,然后设置compiler,如下:
在这里插入图片描述

然后 Shift+Ctrl+Alt+/,选择Registry,然后如下:
在这里插入图片描述
这样就实现热部署了!!!

但是自己鉴于电脑原因,虽然实现了热部署,但是延迟很高,所以还不如手动呢。。。。

springboot全局异常处理

参考文章:
spring的@ControllerAdvice注解

SpringMVC 中 @ControllerAdvice 注解的三种使用场景!

关于这个@ControllerAdvice注解;
解释:

@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。

写一个类,如下:

package com.drillsb.springboot.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

/**
 * 该类是处理异常类
 */
@ControllerAdvice//控制层的增强器
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest request,Exception e){
        ModelAndView mav=new ModelAndView();
        mav.addObject("exception",e);
        mav.addObject("url",request.getRequestURL());
        mav.setViewName("errorPage");
        return mav;
    }
}

然后写一个显示异常的页面errorPage.jsp,如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div style="width:500px;border:1px solid lightgray;margin:200px auto;padding:80px">
    访问该地址出现了异常,异常原因是:<br/>
    ${exception}
    <br/><br/>
    出现异常的该地址是:
    ${url}
</div>
</body>
</html>

然后在随便一个Controller中添加一个异常,如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.DateFormat;
import java.util.Date;

//@RestController//这个注解的意思:==@ResponseBody和Controller

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Model m){
        m.addAttribute("now",
                DateFormat.getDateTimeInstance().format(
                        new Date()));
        if(true){
            throw new RuntimeException("这个是自定义的异常");
        }
        return "hello";
    }

然后访问,就可以看到实现了处理异常的类信息如下:
在这里插入图片描述

application.propertyies的配置

配置端口和上下文路径

在application.properties中配置如下:

server.port=8888  //这个是配置端口
server.context-path=/test //这个是配置访问的上下文路径

其中,以为使用的是1.5版本的springboot,所以配置上下文路径是这样,然后高版本的配置上下文路径,是使用如下:
server.servlet.context-path

反正可以按照提示来,不记得了就看提示的代码如何了;

多配置文件

可以解决在开发和生产环境中使用的端口以及配置等等不一样的问题

在开发中

配置多个文件,如下:

3个配置文件:
核心配置文件:application.properties
开发环境用的配置文件:application-dev.properties
生产环境用的配置文件:application-pro.properties
这样就可以通过application.properties里的spring.profiles.active 灵活地来切换使用哪个环境了

注意了;

其上下文路径配置为 / ,默认就是没有路径的;

核心配置文件中:

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
//使用这个来指定是哪一个环境的配置文件
spring.profiles.active=dev

在开发配置文件application-dev.properties中:

server.port=8080
server.context-path=/

在生成配置文件application-pro.properties中:

server.port=86
server.context-path=/

在项目已经部署中:

不仅可以通过修改application.properties文件进行切换,还可以在部署环境下,指定不同的参数来确保生产环境总是使用的希望的那套配置。

cd C:\Users\X7TI\Downloads\springboot
mvn install

java -jar target/springboot-0.0.1-SNAPSHOT.jar --spring.profiles.active=pro

或者

java -jar target/springboot-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

语句写的是一样的

使用yml

在application.perporties中,可以使用带.yml后缀的文件,其实现的效果是一样的,但是书写格式不太一样,如下为使用yml格式:

spring:
  mvc:
    view:
      prefix: /WEB-INF/jsp/
      suffix: .jsp

server:
  port: 8080
  context-path: /test

注意点

1. 不同“等级” 用冒号隔开 2. 次等级的前面是空格,不能使用制表符(tab) 3. 冒号之后如果有值,那么冒号和值之间至少有一个空格,不能紧贴着

4.后缀为.properties和后缀.yml不能同时使用,不是薛定谔的状态,是确定的!!!也就是必须选择一种。

使用jpa

使用idea连接mysql数据库

方式一:
注意点: 如图所示,连接好mysql之后,如果需要切换所需要的库,应该点击这个地方:

就是这个 1 of 17,这里是可以点击的!!!!!
在这里插入图片描述
方式二:
在这里插入图片描述
然后就进入了,这个页面,点击那个schemas,这个单词的意思就是图表:
在这里插入图片描述

点击之后也可以切换,如下:
在这里插入图片描述

使用jpa规范操作数据库

注意了,这里使用hibernate操作数据库




首先在pom.xml中添加对mysql和jpa的依赖,如下:

<!--        添加对mysql的支持-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>

<!--        添加对jpa的支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

然后在application.properties中添加,一系列连接数据库的参数,如下:

注意点:
这个编码UTF-8要大写!!!
这个编码UTF-8要大写!!!
这个编码UTF-8要大写!!!
server.port=8080
server.context-path=/
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

然后创建hibernate的实体类Category,并且使用注解表示hibernate的相关属性,如下:

package com.drillsb.springboot.pojo;

import javax.persistence.*;

@Entity
@Table(name="category_")
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

数据库中必须要创建跟实体类对应的表,如下:

CREATE database sb_test
use sb_test
create table sb_people(
id int(11) not null auto_increment,
name varchar(20),
primary key(id)
)default charset=utf8;

insert into sb_people values(null,'p1');
insert into sb_people values(null,'p2');
insert into sb_people values(null,'p3');
insert into sb_people values(null,'p4');

然后按照mvc模式,设计CategoryDAO,

该接口继承了jpa的接口,其中泛型里面一个是对应的实体类,另一个是对应实体类的主键类型

如下:

package com.drillsb.springboot.dao;

import com.drillsb.springboot.pojo.Category;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CategoryDAO extends JpaRepository<Category,Integer> {
}

最后设计Controller,按照常规的spring注解,使用,如下:

package com.drillsb.springboot.web;

import com.drillsb.springboot.dao.CategoryDAO;
import com.drillsb.springboot.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class CategoryController {
    @Autowired
    CategoryDAO categoryDAO;

    @RequestMapping("/list")
    public String listCategory(Model m){
        List<Category> cs = categoryDAO.findAll();
        m.addAttribute("cs",cs);
        return "listCategory";
    }
}

最后就是view层了,设计一个jsp,显示查询category表中的数据,listCategory.jsp如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<table border="1" align="center"  cellspacing="0">
    <tr>
       <td>id</td>
       <td>name</td>
    </tr>
    <c:forEach items="${cs}" var="c" varStatus="st">
        <tr>
            <td>${c.id}</td>
            <td>${c.name}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

最终运行SpringbootApplication类中的主方法,然后访问在Controller中设置的访问路径,如下:
在这里插入图片描述

使用jpa规范实现分页增删改查

实体类和依赖,以及使用的框架,都没有变,也就是在上面使用jpa操作数据库的基础上实现crud的;

修改Controller,如下:

package com.drillsb.springboot.web;

import com.drillsb.springboot.dao.CategoryDAO;
import com.drillsb.springboot.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class CategoryController {
    @Autowired
    CategoryDAO categoryDAO;

/*//    这个是查询该Category表的所有内容
    @RequestMapping("/list")
    public String listCategory(Model m){
        List<Category> cs = categoryDAO.findAll();
        m.addAttribute("cs",cs);
        return "listCategory";
    }*/


    @RequestMapping("/listCategory")
    public String listCategory(Model m,
                               @RequestParam(value = "start",defaultValue = "0")int start,
                               @RequestParam(value = "size",defaultValue = "5")int size){
//        当在首页的时候,再点击上一页的情况下
        start=start<0?0:start;
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pb=new PageRequest(start,size,sort);
        Page<Category> page = categoryDAO.findAll(pb);

//        遍历当前页面的分页的数据,返回为list数据,这里就是返回Category的集合
        System.out.println(page.getContent().toString());
//        获取当前页面数
        System.out.println("当前第几页,总是非负的: "+page.getNumber());
        System.out.println("返回当前页上的元素数: "+page.getNumberOfElements());
        System.out.println("返回当前页面的大小: "+page.getSize());
        System.out.println("返回元素总数: "+page.getTotalElements());
//        获取总页面数
        System.out.println("返回分页总数: "+page.getTotalPages());

        m.addAttribute("page",page);
        return "listCategory";
    }

    /*
    * 添加和修改都是使用save,其是根据实体类的id
    * 是否为0来判断是进行添加还是修改
    * */
//    添加
    @RequestMapping("/addCategory")
    public String addCategory(Category category){
        categoryDAO.save(category);
        return "redirect:listCategory";
    }
//    删除
    @RequestMapping("/deleteCategory")
    public String deleteCategory(Category category){
        categoryDAO.delete(category);
        return "redirect:listCategory";
    }
//    修改
    @RequestMapping("/updateCategory")
    public String updateCategory(Category category){
        categoryDAO.save(category);
        return "redirect:listCategory";
    }

//   通过id获取到某一分类的信息
    @RequestMapping("/editCategory")
    public String editCategory(int id,Model m){
//        通过id获取到表信息
        Category c = categoryDAO.getOne(id);
        m.addAttribute("c",c);
        return "editCategory";
    }
}

其中使用jpa实现分页,使用到了Sort类,Page类,Pageable类,PageRequest类,如下:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

这四个类都是spring框架的类;
参考文章:
分页工具一Pageable与Page

Spring Boot中JPA实现Sort排序的三种方式

03:SpringBoot整合SpringDataJPA实现数据库的访问(二)

其中,主要还是Page类,该类实现了Slice类,该类如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.domain;

import java.util.List;
import org.springframework.core.convert.converter.Converter;

public interface Slice<T> extends Iterable<T> {
    int getNumber();

    int getSize();

    int getNumberOfElements();

    List<T> getContent();

    boolean hasContent();

    Sort getSort();

    boolean isFirst();

    boolean isLast();

    boolean hasNext();

    boolean hasPrevious();

    Pageable nextPageable();

    Pageable previousPageable();

    <S> Slice<S> map(Converter<? super T, ? extends S> var1);
}

视图层,listCategory.jsp,如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
   
<div align="center">
 
</div>
 
<div style="width:500px;margin:20px auto;text-align: center">
    <table align='center' border='1' cellspacing='0'>
        <tr>
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${page.content}" var="c" varStatus="st">
            <tr>
                <td>${c.id}</td>
                <td>${c.name}</td>
                <td><a href="editCategory?id=${c.id}">编辑</a></td>
                <td><a href="deleteCategory?id=${c.id}">删除</a></td>
            </tr>
        </c:forEach>
         
    </table>
    <br>
    <div>
                <a href="?start=0">[首  页]</a>
            <a href="?start=${page.number-1}">[上一页]</a>
            <a href="?start=${page.number+1}">[下一页]</a>
            <a href="?start=${page.totalPages-1}">[末  页]</a>
    </div>
    <br>
    <form action="addCategory" method="post">
     
    name: <input name="name"> <br>
    <button type="submit">提交</button>
     
    </form>
</div>
上面的代码,值得注意的是,start是当前第几页;并且是从0开始作为开始页,也就是说第一页为0,第二页为1;所以尾页是总页数-1;

editCategory.jsp,如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>editCategory</title>
</head>
<body>
<div style="margin: 0px auto;width:500px ">
    <form action="updateCategory" method="post">
<%--        --%>
        name:<input name="name" value="${c.name}">
        <input name="id" type="hidden" value="${c.id}">
        <button type="submit">提交</button>
    </form>
</div>
</body>
</html>

启动之后,如下:
在这里插入图片描述




使用mybatis

注解方式

在pom.xml中添加mysql和对mybatis的依赖,如下:

<!--        添加对mysql的支持-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>

<!--        添加对jpa的支持-->
      <!--  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>-->

<!--        添加对mybatis的支持-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>

然后相比于使用hibernate少了许多的配置,配置application.properties文件如下:

server.port=8080
server.context-path=/
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

然后就是实体类,如下:

注意:
这个实体类必须要跟数据库中的表所对应,不然查找不出数据!!!
这个实体类必须要跟数据库中的表所对应,不然查找不出数据!!!
这个实体类必须要跟数据库中的表所对应,不然查找不出数据!!!

也就是mybatis无法实现映射

package com.drillsb.springboot.pojo;

import javax.persistence.*;

/*@Entity
@Table(name="category_")*/
public class Category {
   /* @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")*/
    private int id;

    /*@Column(name="name")*/
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

之后就是DAO类,在mybatis中是使用Mapper接口来代替,如下:

package com.drillsb.springboot.mapper;

import com.drillsb.springboot.pojo.Category;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
@Mapper
public interface CategoryMapper {
    @Select("select * from category_ ")
    List<Category> findAll();
}

其Controller类的处理逻辑是跟使用jpa一样的,如下:

package com.drillsb.springboot.web;

import com.drillsb.springboot.mapper.CategoryMapper;
import com.drillsb.springboot.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class CategoryControllerMybatis {
    @Autowired
    CategoryMapper categoryMapper;

    @RequestMapping("/listCategory")
    public String list(Model m){
        List<Category> cs = categoryMapper.findAll();
        m.addAttribute("cs",cs);
        return "listCategory";
    }

}

运行之后,如下:
在这里插入图片描述

注解方式实现分页增删改查

分页实现采用了第三方的分页插件;

注:xml方式也一样可以实现,只是多了个Mapper类的映射xml的文件而已;

使用了PageHelper分页助手,所以先导依赖包,如下:

<!--        这个是使用mybatis添加分页助手插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>

添加依赖之后,分页助手,按照ssm模式的话,也需要在applicationContext.xml文件中添加对分页助手的配置,但是因为是采用注解方式,所以新建一个类,用于代替配置文件,新建一个PageHelperConfig类,如下:

package com.drillsb.springboot.config;

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration//表示该类是一个配置文件类
public class PageHelperConfig {
    @Bean
    public PageHelper PageHelper(){
        PageHelper pageHelper = new PageHelper();
        Properties p=new Properties();
        p.setProperty("offsetAsPageNum","true");
//        rowBoundsWithCount:设置为true时,使用RowBounds分页会进行count查询.
        p.setProperty("rowBoundsWithCount","true");
//        启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页。
        p.setProperty("reasonable","true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

这个@Bean这个注解,可参考文章,
SpringBoot中 @Bean 和 @Component的联系区别

这个@Bean中不能用于类上!!! 它是用于方法上,表示该方法的返回值存储在spring容器中

除此之外,它是跟@Configuration一起使用的

@Bean不能注释在类上,只能用于在配置类(@Configuration)中显式声明单个bean。意思就是,我要获取这个bean的时候,spring要按照这种方式去获取这个bean。默认情况下@Bean注释的方法名作为对象的名字,也可以用name属性定义对象的名字。


实体类跟前面的一样,保持不变;
然后Mapper类,如下:

package com.drillsb.springboot.mapper;

import com.drillsb.springboot.pojo.Category;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
@Mapper
public interface CategoryMapper {
    @Select("select * from category_ ")
    public List<Category> findAll();

    @Insert("insert into category_(name) values(#{name}) ")
    public int save(Category category);

    @Delete("delete from category_ where id= #{id} ")
    public void delete(int id);

    @Select("select * from category_ where id= #{id} ")
    public Category get(int id);

    @Update("update category_ set name=#{name} where id=#{id} ")
    public int update(Category category);
}

值得注意的是,修改是按照数据库表中id去修改的,但是传递给spring的时候,却是数据库对应的实体类的对象

之后就是控制层了,增删改查,如下:

package com.drillsb.springboot.web;

import com.drillsb.springboot.mapper.CategoryMapper;
import com.drillsb.springboot.pojo.Category;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class CategoryControllerMybatis {
    @Autowired
    CategoryMapper categoryMapper;

    @RequestMapping("/list")
    public String list(Model m,
                       @RequestParam(value = "start",defaultValue = "0")int start,
                       @RequestParam(value = "size",defaultValue = "5") int size){
        PageHelper.startPage(start,size,"id desc");
        List<Category> cs = categoryMapper.findAll();
        PageInfo<Category> pageInfo=new PageInfo<>(cs);
        m.addAttribute("page",pageInfo);
        return "listCategory";
    }

//    增加
    @RequestMapping("/addCategory")
    public String addCategory(Category c){
        categoryMapper.save(c);
        return "redirect:listCategory";
    }
//    删除
    @RequestMapping("/deleteCategory")
    public String deleteCategory(int id){
        categoryMapper.delete(id);
        return "redirect:listCategory";
    }

    //    修改
    @RequestMapping("/updateCategory")
    public String updateCategory(Category category){
        categoryMapper.update(category);
        return "redirect:listCategory";
    }

//    编辑
    @RequestMapping("/editCategory")
    public String editCategory(int id,Model m){
        Category c = categoryMapper.get(id);
        m.addAttribute("c",c);
        return "editCategory";
    }

}

然后listCategory.jsp视图层,如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div style="width: 500px;margin: 20px auto;text-align: center">
    <table border="1" align="center"  cellspacing="0">
        <tr>
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
<%--        page.content获取到Category的数据--%>
        <c:forEach items="${page.list}" var="c" varStatus="st">
            <tr>
                <td>${c.id}</td>
                <td>${c.name}</td>
                <td><a href="editCategory?id=${c.id}">编辑</a></td>
                <td><a href="deleteCategory?id=${c.id}">删除</a></td>
            </tr>
        </c:forEach>
    </table>
    <br/>
    <div>
        <a href="?start=0">[首 页]</a>
        <a href="?start=${page.pageNum-1}">[上一页]</a>
        <a href="?start=${page.pageNum+1}">[下一页]</a>
        <a href="?start=${page.pages}">[末 页]</a>
    </div>
    <br/>
    <form action="addCategory" method="post">
        name:<input name="name"><br/>
        <button type="submit">提交</button>
    </form>
</div>

</body>
</html>

其数据的获取跟前面使用jpa不同,使用的是分页助手获取数据的;

editCategory.jsp如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>editCategory</title>
</head>
<body>
<div style="margin: 0px auto;width:500px ">
    <form action="updateCategory" method="post">
        name:<input name="name" value="${c.name}">
        <input name="id" type="hidden" value="${c.id}">
        <button type="submit">提交</button>
    </form>
</div>
</body>
</html>

启动之后,如下:
在这里插入图片描述




xml方式

Controller和实体类不需要改变,只是将Mapper接口的映射方式,改为使用xml文件,Mapper类改为如下:

package com.drillsb.springboot.mapper;

import com.drillsb.springboot.pojo.Category;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
@Mapper
public interface CategoryMapper {
    List<Category> findAll();
}

然后在application.properties文件中添加,对Mapper映射文件的地址,以及别名,如下:

server.port=8080
server.context-path=/
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

mybatis.mapper-locations=classpath:com/drillsb/springboot/mapper/*.xml
mybatis.type-aliases-package=com.drillsb.springboot.pojo

最后其Mapper的配置文件,得在resource目录下,即资源文件目录下,如下图所示:
在这里插入图片描述

除此之外,还有一个很重要的点是! 这个resource中是目录结构,对应着application.properties中的

mybatis.mapper-locations=classpath:com/drillsb/springboot/mapper/*.xml

这个路径名!!!!!
因而言,创建该目录的时候,就该如下图所示创建:

在这里插入图片描述
而不能用.分隔符创建!!!
其创建的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="com.drillsb.springboot.mapper.CategoryMapper">
    <select id="findAll" resultType="Category">
        select * from category_
    </select>
</mapper>

运行还是没有问题的,这样也就完成了跟注解一样的效果!

使用sqlite

这个数据库的详细内容,参考文章如下:
sqlite教程和简介

总而言之,这是一个无须配置的内存数据库;

SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL
数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。

首先在pom.xml添加依赖,如下:

<!--        添加对sqlite的依赖-->
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>

然后添加三个类,说实话对这三个类一窍不通。。。。如下:
SQLiteDialect类:

package com.drillsb.springboot.sqlite;

import org.hibernate.JDBCException;
import org.hibernate.ScrollMode;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.*;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.exception.DataException;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.mapping.Column;
import org.hibernate.type.StandardBasicTypes;

import java.sql.SQLException;
import java.sql.Types;

public class SQLiteDialect extends Dialect {
    private final UniqueDelegate uniqueDelegate;

    public SQLiteDialect() {
        registerColumnType(Types.BIT, "boolean");
        registerColumnType(Types.DECIMAL, "decimal");
        registerColumnType(Types.CHAR, "char");
        registerColumnType(Types.LONGVARCHAR, "longvarchar");
        registerColumnType(Types.TIMESTAMP, "datetime");
        registerColumnType(Types.BINARY, "blob");
        registerColumnType(Types.VARBINARY, "blob");
        registerColumnType(Types.LONGVARBINARY, "blob");

        registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", ""));
        registerFunction("mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2"));
        registerFunction("quote", new StandardSQLFunction("quote", StandardBasicTypes.STRING));
        registerFunction("random", new NoArgSQLFunction("random", StandardBasicTypes.INTEGER));
        registerFunction("round", new StandardSQLFunction("round"));
        registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
        registerFunction("trim", new AbstractAnsiTrimEmulationFunction() {
            @Override
            protected SQLFunction resolveBothSpaceTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1)");
            }

            @Override
            protected SQLFunction resolveBothSpaceTrimFromFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?2)");
            }

            @Override
            protected SQLFunction resolveLeadingSpaceTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1)");
            }

            @Override
            protected SQLFunction resolveTrailingSpaceTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1)");
            }

            @Override
            protected SQLFunction resolveBothTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1, ?2)");
            }

            @Override
            protected SQLFunction resolveLeadingTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1, ?2)");
            }

            @Override
            protected SQLFunction resolveTrailingTrimFunction() {
                return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1, ?2)");
            }
        });
        uniqueDelegate = new SQLiteUniqueDelegate(this);
    }

    private static final SQLiteDialectIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new
            SQLiteDialectIdentityColumnSupport(new SQLiteDialect());

    @Override
    public IdentityColumnSupport getIdentityColumnSupport() {
        return IDENTITY_COLUMN_SUPPORT;
    }

    // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    private static final AbstractLimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
        @Override
        public String processSql(String sql, RowSelection selection) {
            final boolean hasOffset = LimitHelper.hasFirstRow(selection);
            return sql + (hasOffset ? " limit ? offset ?" : " limit ?");
        }

        @Override
        public boolean supportsLimit() {
            return true;
        }

        @Override
        public boolean bindLimitParametersInReverseOrder() {
            return true;
        }
    };

    @Override
    public LimitHandler getLimitHandler() {
        return LIMIT_HANDLER;
    }

    // lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override
    public boolean supportsLockTimeouts() {
        // may be http://sqlite.org/c3ref/db_mutex.html ?
        return false;
    }

    @Override
    public String getForUpdateString() {
        return "";
    }

    @Override
    public boolean supportsOuterJoinForUpdate() {
        return false;
    }

    // current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Override
    public boolean supportsCurrentTimestampSelection() {
        return true;
    }

    @Override
    public boolean isCurrentTimestampSelectStringCallable() {
        return false;
    }

    @Override
    public String getCurrentTimestampSelectString() {
        return "select current_timestamp";
    }

    // SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final int SQLITE_BUSY = 5;
    private static final int SQLITE_LOCKED = 6;
    private static final int SQLITE_IOERR = 10;
    private static final int SQLITE_CORRUPT = 11;
    private static final int SQLITE_NOTFOUND = 12;
    private static final int SQLITE_FULL = 13;
    private static final int SQLITE_CANTOPEN = 14;
    private static final int SQLITE_PROTOCOL = 15;
    private static final int SQLITE_TOOBIG = 18;
    private static final int SQLITE_CONSTRAINT = 19;
    private static final int SQLITE_MISMATCH = 20;
    private static final int SQLITE_NOTADB = 26;

    @Override
    public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
        return new SQLExceptionConversionDelegate() {
            @Override
            public JDBCException convert(SQLException sqlException, String message, String sql) {
                final int errorCode = JdbcExceptionHelper.extractErrorCode(sqlException) & 0xFF;
                if (errorCode == SQLITE_TOOBIG || errorCode == SQLITE_MISMATCH) {
                    return new DataException(message, sqlException, sql);
                } else if (errorCode == SQLITE_BUSY || errorCode == SQLITE_LOCKED) {
                    return new LockAcquisitionException(message, sqlException, sql);
                } else if ((errorCode >= SQLITE_IOERR && errorCode <= SQLITE_PROTOCOL) || errorCode == SQLITE_NOTADB) {
                    return new JDBCConnectionException(message, sqlException, sql);
                }

                // returning null allows other delegates to operate
                return null;
            }
        };
    }

    @Override
    public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
        return EXTRACTER;
    }

    private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
        @Override
        protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
            final int errorCode = JdbcExceptionHelper.extractErrorCode(sqle) & 0xFF;
            if (errorCode == SQLITE_CONSTRAINT) {
                return extractUsingTemplate("constraint ", " failed", sqle.getMessage());
            }
            return null;
        }
    };

    // union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Override
    public boolean supportsUnionAll() {
        return true;
    }

    // DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Override
    public boolean canCreateSchema() {
        return false;
    }

    @Override
    public boolean hasAlterTable() {
        // As specified in NHibernate dialect
        return false;
    }

    @Override
    public boolean dropConstraints() {
        return false;
    }

    @Override
    public boolean qualifyIndexName() {
        return false;
    }

    @Override
    public String getAddColumnString() {
        return "add column";
    }

    @Override
    public String getDropForeignKeyString() {
        throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect");
    }

    @Override
    public String getAddForeignKeyConstraintString(String constraintName,
                                                   String[] foreignKey, String referencedTable, String[] primaryKey,
                                                   boolean referencesPrimaryKey) {
        throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect");
    }

    @Override
    public String getAddPrimaryKeyConstraintString(String constraintName) {
        throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect");
    }

    @Override
    public boolean supportsCommentOn() {
        return true;
    }

    @Override
    public boolean supportsIfExistsBeforeTableName() {
        return true;
    }

    @Override
    public boolean doesReadCommittedCauseWritersToBlockReaders() {
        // TODO Validate (WAL mode...)
        return true;
    }

    @Override
    public boolean doesRepeatableReadCauseReadersToBlockWriters() {
        return true;
    }

    @Override
    public boolean supportsTupleDistinctCounts() {
        return false;
    }

    @Override
    public int getInExpressionCountLimit() {
        return 1000;
    }

    @Override
    public UniqueDelegate getUniqueDelegate() {
        return uniqueDelegate;
    }

    private static class SQLiteUniqueDelegate extends DefaultUniqueDelegate {
        public SQLiteUniqueDelegate(Dialect dialect) {
            super(dialect);
        }

        @Override
        public String getColumnDefinitionUniquenessFragment(Column column) {
            return " unique";
        }
    }

    @Override
    public String getSelectGUIDString() {
        return "select hex(randomblob(16))";
    }

    @Override
    public ScrollMode defaultScrollMode() {
        return ScrollMode.FORWARD_ONLY;
    }
}

SQLiteDialectIdentityColumnSupport类

package com.drillsb.springboot.sqlite;

import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.IdentityColumnSupportImpl;

public class SQLiteDialectIdentityColumnSupport extends IdentityColumnSupportImpl {
    public SQLiteDialectIdentityColumnSupport(Dialect dialect) {
        super(dialect);
    }
    @Override
    public boolean supportsIdentityColumns() {
        return true;
    }

    @Override
    public boolean hasDataTypeInIdentityColumn() {
        return false;
    }

    @Override
    public String getIdentitySelectString(String table, String column, int type) {
        return "select last_insert_rowid()";
    }

    @Override
    public String getIdentityColumnString(int type) {
        return "integer";
    }
}

SQLiteMetadataBuilderInitializer类

package com.drillsb.springboot.sqlite;

import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.MetadataBuilderInitializer;
import org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.jboss.logging.Logger;


public class SQLiteMetadataBuilderInitializer implements MetadataBuilderInitializer {

    private final static Logger logger = Logger.getLogger(SQLiteMetadataBuilderInitializer.class);

    @Override
    public void contribute(MetadataBuilder metadataBuilder, StandardServiceRegistry serviceRegistry) {
        DialectResolver dialectResolver = serviceRegistry.getService(DialectResolver.class);

        if (!(dialectResolver instanceof DialectResolverSet)) {
            logger.warnf("DialectResolver '%s' is not an instance of DialectResolverSet, not registering SQLiteDialect",
                    dialectResolver);
            return;
        }

        ((DialectResolverSet) dialectResolver).addResolver(resolver);
    }

    static private final SQLiteDialect dialect = new SQLiteDialect();

    static private final DialectResolver resolver = (DialectResolver) info -> {
        if (info.getDatabaseName().equals("SQLite")) {
            return dialect;
        }

        return null;
    };
}

然后就是在application.properties中添加对sqlite数据库的支持,如下:

#这个是对sqlite的配置
spring.jpa.database-platform=com.drillsb.springboot.sqlite.SQLiteDialect

#表结构由hibernate根据实体类来创建
spring.jpa.generate-ddl=true

#自动根据pojo配置创建表
spring.jpa.hibernate.ddl-auto=update

#数据库文件位置
spring.datasource.url=jdbc:sqlite:example.db

#驱动名称
spring.datasource.tomcat.driver-class-name=org.sqlite.JDBC

因为只是对持久层改变,所以其他的不用修改;之后重启,然后访问地址之后是一篇空白的。。。因为还没有数据,所以需要自己一点一点的添加数据进去,添加之后访问如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值