SpringBoot内嵌数据库的使用(H2)
配置数据源(DataSource)
Java的javax.sql.DataSource接口提供了一个标准的使用数据库连接的方法。 传统做法是, 一个DataSource使用一个URL以及相应的证书去构建一个数据库连接。
内嵌数据库的支持
在开发应用的过程中使用内嵌的内存数据库是非常方便的,很明显,内存数据库不提供数据的持久化存储;当应用启动时你需要填充你的数据库,当应用结束时数据将会丢弃。
Spring Boot可以自动的配置内嵌的H2、HSQL、Derby数据库。你不需要提供任何链接URLs,只需要简单的提供一个你需要使用的内嵌数据库的依赖即可。
如果在测试时要使用内嵌数据库的功能,需要注意在默认情况下无论使用多少个应用上下文在整个测试过程中相同的数据库都是可用复用的。如果想要让每个应用上下文使用隔离的内嵌数据库,应该设置spring.datasource.generate-unique-name为ture。
内嵌数据库的使用
本文通过演示H2内嵌数据库的使用来帮助理解在Spring Boot中如何使用内嵌数据库。
要使用H2内嵌数据库,首先需要添加JPA和H2的依赖,但是我们从数据库读取数据之后,需要展示在页面上,所以需要配置一个模板引擎,本文选择thymeleaf作为我们应用的模板引擎,所以也需要添加对thymeleaf的依赖。
添加之后的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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
对于我们的示例程序来说,我们需要创建一个实体类,类名我们将其命名为Journal,具体详细信息如下。
package com.springboot.domain; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Transient; @Entity public class Journal { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; private String title; private Date created; private String summary; @Transient private SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy"); public Journal(String title, String summary, String date) throws ParseException{ this.title = title; this.summary = summary; this.created = format.parse(date); } Journal(){} public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public String getCreatedAsShort(){ return format.format(created); } public String toString(){ StringBuilder value = new StringBuilder("JournalEntry("); value.append("Id: "); value.append(id); value.append(",Title: "); value.append(title); value.append(",Summary: "); value.append(summary); value.append(",Created: "); value.append(getCreatedAsShort()); value.append(")"); return value.toString(); } }
在上面的代码片段中,因为使用了JPA技术,所以你需要使用@Entity, @Id和@GeneratedValue注解,因此这个类被标记作为JPA实体并且能够被持久化到数据库中。你也可以看到,在我们的代码中也使用了@Transient注解,这个注解表示JPA引擎不会持久化被注解的属性,因为上面的代码片中被@Transient注解的属性仅仅只是用来格式化日期。这个类有两个构造函数,一个没有参数,JPA引擎需要这个构造函数,另外一个构造函数需要用来填充数据库的参数。
我们覆盖(override)了一个toString方法,主要用来打印记录。
接下来,我们需要为数据创建一个持久化机制,那么我们就需要使用Spring Data JPA技术了,
创建一个接口,继承JpaRepository接口。代码如下。
package com.springboot.repository; import com.springboot.domain.Journal; import org.springframework.data.jpa.repository.JpaRepository; public interface JournalRepository extends JpaRepository<Journal,Long> { }
上面的代码片所展示的是Spring Data Repository JPA技术,要使用这项技术只需要继承JpaRepository接口即可。JpaRepository是一个标记接口,允许Spring Data Repository引擎识别它并提供必要的代理类来实现基本的CRUD (Create, Read, Update, Delete) 和一些自定义的方法。你可以通过一些类似于findByTitleLike、findBySummary、findByTitleAndSummaryIgnoringCase等等命名约定去实现你的方法。默认情况下,这些方法所实现的功能都会被设置成一个事务。JpaRepository也有一些非常便捷的操作可以对数据进行排序和分页的操作。
接下来,我们需要创建一个Web controller。
package com.springboot.web; import com.springboot.repository.JournalRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class JournalController { @Autowired JournalRepository repo; @RequestMapping("/") public String index(Model model){ model.addAttribute("journal", repo.findAll()); return "index"; } }
@Controller注解、@Autowired注解、@RequestMapping注解我们不在详细介绍,如果使用过Spring MVC开发过应用,这些注解基本都已经了如指掌。在我们的index方法中,有一个Model类的参数,他用来添加一个名为journal的属性值,该属性的值通过调用JournalRepository接口repo.findAll() 获取。JournalRepository继承自JpaRepository,所以该接口有很多不同的默认方法,findAll方法就是其中之一。该方法返回数据库中所有的实体。
接下来我们需要构建模板文件,在src/main/resources/templates目录下,需要创建一个index.html文件并写入如下内容。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"></meta> <meta http-equiv="Content-Type" content="text/html"></meta> <title>Spring Boot Journal</title> <link rel="stylesheet" type="text/css" media="all" href="css/bootstrap.min.css"></link> </head> <body> <h1>Spring Boot Journal</h1> <ul class="timeline"> <div th:each="entry,status : ${journal}"> <li th:attr="class=${status.odd}?'timeline-inverted':''"> <div class="tl-circ"></div> <div class="timeline-panel"> <div class="tl-heading"> <h4><span th:text="${entry.title}">TITLE</span></h4> <p><small class="text-muted"><i class="glyphicon glyphicon-time"></i> <span th:text="${entry.createdAsShort}">CREATED</span></small></p> </div> <div class="tl-body"> <p><span th:text="${entry.summary}">SUMMARY</span></p> </div> </div> </li> </div> </ul> </body> </html>
注意:在static目录下新建一个css目录,添加bootstrap.min.css文件,该文件自行到bootstrap去下载。
现在,就剩下最重要的一步,构建数据和实现应用入口。代码如下;
package com.springboot; import com.springboot.domain.Journal; import com.springboot.repository.JournalRepository; import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class DemoApplication { @Bean InitializingBean saveData(JournalRepository repo){ return ()->{ repo.save(new Journal("Get to know Spring Boot","Today I will learn Spring Boot","01/01/2016")); repo.save(new Journal("Simple Spring Boot Project","I will do my first Spring Boot Project","01/02/2016")); repo.save(new Journal("Spring Boot Reading","Read more about Spring Boot","02/01/2016")); repo.save(new Journal("Spring Boot in the Cloud","Spring Boot using Cloud Foundry","03/01/2016")); }; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
注意:这里要提及的一点就是saveData方法返回的是一个InitializingBean,这个特殊的类在Spring引擎创建序列化实例时会被调用。在本示例中,这个方法将会在应用完成运行的过程中被执行。
转载自 https://blog.csdn.net/zyhlwzy/article/details/78733644 ,感谢作者。
参考文档2:https://blog.csdn.net/mn960mn/article/details/54644908