springBoot基础(一)
发布日期:2021-07-27 04:54:53 浏览次数:9 分类:技术文章

本文共 36329 字,大约阅读时间需要 121 分钟。

文章目录


前言

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

创建idea集成的springBoot项目

第一步:直接创建就ok,如下:

在这里插入图片描述
然后下一步;最终会形成一个这样的目录结构:
在这里插入图片描述

在springBoot中使用jsp

第一步添加依赖:

在pom.xml中,如下:

4.0.0
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
com.drillsb
springboot
0.0.1-SNAPSHOT
springboot
war
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.junit.jupiter
junit-jupiter
RELEASE
test
javax.servlet
javax.servlet-api
javax.servlet
jstl
org.apache.tomcat.embed
tomcat-embed-jasper
org.springframework.boot
spring-boot-maven-plugin
src/main/webapp
META-INF/resources
**/*.*

注意点:

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

javax.servlet
javax.servlet-api
javax.servlet
jstl
org.apache.tomcat.embed
tomcat-embed-jasper
注意了,必须要指明资源的路径,也就是在pom.xml中添加资源的路径,如下:
src/main/webapp
META-INF/resources
**/*.*
除此之外,跟原来的web项目一样,也要指定资源路径,如下:

在这里插入图片描述

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

在spring中启动热部署

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

org.springframework.boot
spring-boot-devtools
true
org.springframework.boot
spring-boot-maven-plugin

这样在idea中还是实现不了热部署的。。。。因为在idea中默认情况下是不会进行热部署,所以要设置几步;

首先,打开idea的setting设置,然后设置compiler,如下:
在这里插入图片描述

然后 Shift+Ctrl+Alt+/,选择Registry,然后如下:

在这里插入图片描述
这样就实现热部署了!!!

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

springboot全局异常处理

参考文章:

关于这个@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" %>    Title
访问该地址出现了异常,异常原因是:
${
exception}
出现异常的该地址是: ${
url}

然后在随便一个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@Controllerpublic 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=8080server.context-path=/

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

server.port=86server.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: .jspserver:  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
mysql-connector-java
5.1.21
org.springframework.boot
spring-boot-starter-data-jpa

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

注意点:
这个编码UTF-8要大写!!!
这个编码UTF-8要大写!!!
这个编码UTF-8要大写!!!
server.port=8080server.context-path=/spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=adminspring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.jpa.properties.hibernate.hbm2ddl.auto=updatespring.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_testuse sb_testcreate 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
{
}

最后设计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;@Controllerpublic class CategoryController {
@Autowired CategoryDAO categoryDAO; @RequestMapping("/list") public String listCategory(Model m){
List
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" %>    Title
id name
${
c.id}
${
c.name}

最终运行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;@Controllerpublic class CategoryController {
@Autowired CategoryDAO categoryDAO;/*// 这个是查询该Category表的所有内容 @RequestMapping("/list") public String listCategory(Model m){ List
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
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框架的类;

参考文章:

其中,主要还是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
extends Iterable
{
int getNumber(); int getSize(); int getNumberOfElements(); List
getContent(); boolean hasContent(); Sort getSort(); boolean isFirst(); boolean isLast(); boolean hasNext(); boolean hasPrevious(); Pageable nextPageable(); Pageable previousPageable();
Slice map(Converter
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"%>   
id name 编辑 删除
${
c.id}
${
c.name}
编辑 删除
name:
上面的代码,值得注意的是,start是当前第几页;并且是从0开始作为开始页,也就是说第一页为0,第二页为1;所以尾页是总页数-1;

editCategory.jsp,如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>    editCategory
<%-- --%> name:

启动之后,如下:

在这里插入图片描述

使用mybatis

注解方式

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

mysql
mysql-connector-java
5.1.21
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1

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

server.port=8080server.context-path=/spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=adminspring.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@Mapperpublic interface CategoryMapper {
@Select("select * from category_ ") List
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;@Controllerpublic class CategoryControllerMybatis {
@Autowired CategoryMapper categoryMapper; @RequestMapping("/listCategory") public String list(Model m){
List
cs = categoryMapper.findAll(); m.addAttribute("cs",cs); return "listCategory"; }}

运行之后,如下:

在这里插入图片描述

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

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

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

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

com.github.pagehelper
pagehelper
4.1.6

添加依赖之后,分页助手,按照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这个注解,可参考文章,

这个@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@Mapperpublic interface CategoryMapper {
@Select("select * from category_ ") public List
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;@Controllerpublic 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
cs = categoryMapper.findAll(); PageInfo
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" %>    Title
<%-- page.content获取到Category的数据--%>
id name 编辑 删除
${
c.id}
${
c.name}
编辑 删除
name:

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

editCategory.jsp如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>    editCategory
name:

启动之后,如下:

在这里插入图片描述

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@Mapperpublic interface CategoryMapper {
List
findAll();}

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

server.port=8080server.context-path=/spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sb_test?characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=adminspring.datasource.driver-class-name=com.mysql.jdbc.Drivermybatis.mapper-locations=classpath:com/drillsb/springboot/mapper/*.xmlmybatis.type-aliases-package=com.drillsb.springboot.pojo

最后其Mapper的配置文件,得在resource目录下,即资源文件目录下,如下图所示:

在这里插入图片描述

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

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

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

在这里插入图片描述

而不能用.分隔符创建!!!
其创建的Mapper映射文件如下:

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

使用sqlite

这个数据库的详细内容,参考文章如下:

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

SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL

数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。

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

org.xerial
sqlite-jdbc
runtime

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

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

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

在这里插入图片描述

转载地址:https://blog.csdn.net/qq_45321679/article/details/112949083 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:springBoot相关问题
下一篇:杂文之Io

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年09月30日 22时19分16秒