(window.webpackJsonp=window.webpackJsonp||[]).push([[399],{834:function(e,t,a){"use strict";a.r(t);var r=a(56),n=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"数据"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据"}},[e._v("#")]),e._v(" 数据")]),e._v(" "),a("p",[e._v("Spring Boot 集成了许多数据技术,包括 SQL 和 NoSQL。")]),e._v(" "),a("h1",{attrs:{id:"_1-sql-数据库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-sql-数据库"}},[e._v("#")]),e._v(" 1. SQL 数据库")]),e._v(" "),a("hr"),e._v(" "),a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-framework",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Framework"),a("OutboundLink")],1),e._v("为使用 SQL 数据库提供了广泛的支持,从使用"),a("code",[e._v("JdbcTemplate")]),e._v("直接访问 JDBC 到完成诸如 Hibernate 之类的“对象关系映射”技术。"),a("a",{attrs:{href:"https://spring.io/projects/spring-data",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data"),a("OutboundLink")],1),e._v("提供了一个额外的功能级别:直接从接口创建"),a("code",[e._v("Repository")]),e._v("实现,并使用约定从你的方法名称生成查询。")]),e._v(" "),a("h3",{attrs:{id:"_1-1-配置数据源"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-配置数据源"}},[e._v("#")]),e._v(" 1.1.配置数据源")]),e._v(" "),a("p",[e._v("Java 的"),a("code",[e._v("javax.sql.DataSource")]),e._v("接口提供了一种处理数据库连接的标准方法。传统上,“数据源”使用"),a("code",[e._v("URL")]),e._v("以及一些凭据来建立数据库连接。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关更高级的示例,请参见"),a("RouterLink",{attrs:{to:"/spring-boot/howto.html#howto.data-access.configure-custom-datasource"}},[e._v("“操作指南”部分")]),e._v(",通常用于完全控制数据源的配置。")],1)])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-1-1-嵌入式数据库支持"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-1-嵌入式数据库支持"}},[e._v("#")]),e._v(" 1.1.1.嵌入式数据库支持")]),e._v(" "),a("p",[e._v("使用嵌入式数据库开发应用程序通常是很方便的。显然,内存数据库不提供持久存储。你需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("“how-to”部分包括"),a("RouterLink",{attrs:{to:"/spring-boot/howto.html#howto.data-initialization"}},[e._v("关于如何初始化数据库的一节")]),e._v("。")],1)])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("Spring 引导可以自动配置嵌入式"),a("a",{attrs:{href:"https://www.h2database.com",target:"_blank",rel:"noopener noreferrer"}},[e._v("H2"),a("OutboundLink")],1),e._v("、"),a("a",{attrs:{href:"http://hsqldb.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("HSQL"),a("OutboundLink")],1),e._v("和"),a("a",{attrs:{href:"https://db.apache.org/derby/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Derby"),a("OutboundLink")],1),e._v("数据库。你不需要提供任何连接 URL。你只需要对要使用的嵌入式数据库包含一个构建依赖项。如果在 Classpath 上有多个嵌入式数据库,请设置"),a("code",[e._v("spring.datasource.embedded-database-connection")]),e._v("配置属性以控制使用哪个数据库。将属性设置为"),a("code",[e._v("none")]),e._v("将禁用嵌入式数据库的自动配置。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果你在测试中使用此功能,你可能会注意到,无论你使用的应用程序上下文的数量如何,整个测试套件都可以重用相同的数据库,如果你想确保每个上下文都有一个单独的嵌入式数据库,"),a("br"),e._v(",你应该将"),a("code",[e._v("spring.datasource.generate-unique-name")]),e._v("设置为"),a("code",[e._v("true")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("例如,典型的 POM 依赖关系如下:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("\n org.springframework.boot\n spring-boot-starter-data-jpa\n\n\n org.hsqldb\n hsqldb\n runtime\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你需要对"),a("code",[e._v("spring-jdbc")]),e._v("有一个依赖关系,才能自动配置嵌入式数据库。"),a("br"),e._v("在本例中,它是通过"),a("code",[e._v("spring-boot-starter-data-jpa")]),e._v("传递地拉入的。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("无论出于何种原因,如果你确实为嵌入式数据库配置了连接 URL,请注意确保禁用数据库的自动关闭。"),a("br"),e._v("如果你使用 H2,则应使用"),a("code",[e._v("DB_CLOSE_ON_EXIT=FALSE")]),e._v(",如果你使用 HSQLDB,请使用"),a("br"),e._v(",你应该确保不使用"),a("code",[e._v("shutdown=true")]),e._v("。"),a("br"),e._v("禁用数据库的自动关机可以在数据库关闭时进行引导控制,从而确保在不再需要访问数据库时发生这种情况。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-1-2-与生产数据库的连接"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-2-与生产数据库的连接"}},[e._v("#")]),e._v(" 1.1.2.与生产数据库的连接")]),e._v(" "),a("p",[e._v("还可以通过使用池"),a("code",[e._v("DataSource")]),e._v("自动配置生产数据库连接。")]),e._v(" "),a("h4",{attrs:{id:"_1-1-3-数据源配置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-3-数据源配置"}},[e._v("#")]),e._v(" 1.1.3.数据源配置")]),e._v(" "),a("p",[e._v("数据源配置由"),a("code",[e._v("spring.datasource.*")]),e._v("中的外部配置属性控制。例如,你可以在"),a("code",[e._v("application.properties")]),e._v("中声明以下部分:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.datasource.url=jdbc:mysql://localhost/test\nspring.datasource.username=dbuser\nspring.datasource.password=dbpass\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n datasource:\n url: "jdbc:mysql://localhost/test"\n username: "dbuser"\n password: "dbpass"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你至少应该通过设置"),a("code",[e._v("spring.datasource.url")]),e._v("属性来指定 URL。"),a("br"),e._v("否则, Spring 引导将尝试自动配置嵌入式数据库。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Spring 引导可以从 URL 推断出大多数数据库的 JDBC 驱动程序类。"),a("br"),e._v("如果需要指定特定的类,可以使用"),a("code",[e._v("spring.datasource.driver-class-name")]),e._v("属性。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("对于要创建的池"),a("code",[e._v("DataSource")]),e._v(",我们需要能够验证一个有效的"),a("code",[e._v("Driver")]),e._v("类是可用的,所以我们在做任何事情之前都要检查它。"),a("br"),e._v("换句话说,如果你设置"),a("code",[e._v("spring.datasource.driver-class-name=com.mysql.jdbc.Driver")]),e._v(",那么这个类必须是可加载的。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("参见["),a("code",[e._v("DataSource属性")]),e._v("](https://github.com/ Spring-projects/ Spring-boot/tree/v2.6.4/ Spring-boot-project/ Spring-boot-autofigure/SRC/main/java/org/springframework/boot/autofigure/jdbc/dasourceproperties.java)以获得更多支持的选项。无论"),a("RouterLink",{attrs:{to:"/spring-boot/features.html#data.sql.datasource.connection-pool"}},[e._v("实际执行情况")]),e._v("如何,这些都是标准选项。也可以通过使用它们各自的前缀("),a("code",[e._v("spring.datasource.hikari.*")]),e._v(","),a("code",[e._v("spring.datasource.tomcat.*")]),e._v(","),a("code",[e._v("spring.datasource.dbcp2.*")]),e._v(",和"),a("code",[e._v("spring.datasource.oracleucp.*")]),e._v(")来微调实现特定的设置。有关更多详细信息,请参见你正在使用的连接池实现的文档。")],1),e._v(" "),a("p",[e._v("例如,如果使用"),a("a",{attrs:{href:"https://tomcat.apache.org/tomcat-9.0-doc/jdbc-pool.html#Common_Attributes",target:"_blank",rel:"noopener noreferrer"}},[e._v("Tomcat connection pool"),a("OutboundLink")],1),e._v(",则可以自定义许多其他设置,如下例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.datasource.tomcat.max-wait=10000\nspring.datasource.tomcat.max-active=50\nspring.datasource.tomcat.test-on-borrow=true\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring:\n datasource:\n tomcat:\n max-wait: 10000\n max-active: 50\n test-on-borrow: true\n")])])]),a("p",[e._v("这将设置池等待 10000ms,然后在没有可用连接的情况下抛出异常,将最大连接数量限制为 50,并在从池中借用连接之前验证连接。")]),e._v(" "),a("h4",{attrs:{id:"_1-1-4-支持的连接池"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-4-支持的连接池"}},[e._v("#")]),e._v(" 1.1.4.支持的连接池")]),e._v(" "),a("p",[e._v("Spring 启动使用以下算法来选择具体的实现方式:")]),e._v(" "),a("ol",[a("li",[a("p",[e._v("我们更喜欢"),a("a",{attrs:{href:"https://github.com/brettwooldridge/HikariCP",target:"_blank",rel:"noopener noreferrer"}},[e._v("Hikaricp"),a("OutboundLink")],1),e._v("的性能和并发性。如果有 Hikaricp,我们总是选择它。")])]),e._v(" "),a("li",[a("p",[e._v("否则,如果 Tomcat 池"),a("code",[e._v("DataSource")]),e._v("可用,则使用它。")])]),e._v(" "),a("li",[a("p",[e._v("否则,如果"),a("a",{attrs:{href:"https://commons.apache.org/proper/commons-dbcp/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Commons DBCP2"),a("OutboundLink")],1),e._v("是可用的,我们就使用它。")])]),e._v(" "),a("li",[a("p",[e._v("如果 HIKARICP、 Tomcat 和 DBCP2 都不可用,并且如果 Oracle UCP 可用,我们就使用它。")])])]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果使用"),a("code",[e._v("spring-boot-starter-jdbc")]),e._v("或"),a("code",[e._v("spring-boot-starter-data-jpa")]),e._v("“starters”,则会自动获得对"),a("code",[e._v("HikariCP")]),e._v("的依赖关系。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("你可以完全绕过该算法,并通过设置"),a("code",[e._v("spring.datasource.type")]),e._v("属性来指定要使用的连接池。如果你在 Tomcat 容器中运行应用程序,这一点尤其重要,因为"),a("code",[e._v("tomcat-jdbc")]),e._v("是默认提供的。")]),e._v(" "),a("p",[e._v("总是可以使用"),a("code",[e._v("DataSourceBuilder")]),e._v("手动配置其他连接池。如果你定义了自己的"),a("code",[e._v("DataSource")]),e._v(" Bean,则不会发生自动配置。"),a("code",[e._v("DataSourceBuilder")]),e._v("支持以下连接池:")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("HikariCP")])]),e._v(" "),a("li",[a("p",[e._v("Tomcat 池"),a("code",[e._v("Datasource")])])]),e._v(" "),a("li",[a("p",[e._v("Commons DBCP2")])]),e._v(" "),a("li",[a("p",[e._v("Oracle UCP&"),a("code",[e._v("OracleDataSource")])])]),e._v(" "),a("li",[a("p",[e._v("Spring 框架的"),a("code",[e._v("SimpleDriverDataSource")])])]),e._v(" "),a("li",[a("p",[e._v("h2"),a("code",[e._v("JdbcDataSource")])])]),e._v(" "),a("li",[a("p",[e._v("PostgreSQL"),a("code",[e._v("PGSimpleDataSource")])])])]),e._v(" "),a("h4",{attrs:{id:"_1-1-5-连接到-jndi-数据源"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-5-连接到-jndi-数据源"}},[e._v("#")]),e._v(" 1.1.5.连接到 JNDI 数据源")]),e._v(" "),a("p",[e._v("如果你将 Spring 引导应用程序部署到应用程序服务器,那么你可能希望通过使用应用程序服务器的内置功能来配置和管理你的数据源,并通过使用 JNDI 访问它。")]),e._v(" "),a("p",[a("code",[e._v("spring.datasource.jndi-name")]),e._v("属性可以用作"),a("code",[e._v("spring.datasource.url")]),e._v("、"),a("code",[e._v("spring.datasource.username")]),e._v("和"),a("code",[e._v("spring.datasource.password")]),e._v("属性的替代选项,以从特定的 JNDI 位置访问"),a("code",[e._v("DataSource")]),e._v("。例如,"),a("code",[e._v("application.properties")]),e._v("中的以下部分显示了如何按照"),a("code",[e._v("DataSource")]),e._v("的定义访问 JBoss:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.datasource.jndi-name=java:jboss/datasources/customers\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n datasource:\n jndi-name: "java:jboss/datasources/customers"\n')])])]),a("h3",{attrs:{id:"_1-2-使用-jdbctemplate"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-2-使用-jdbctemplate"}},[e._v("#")]),e._v(" 1.2.使用 JDBCTemplate")]),e._v(" "),a("p",[e._v("Spring 的"),a("code",[e._v("JdbcTemplate")]),e._v("和"),a("code",[e._v("NamedParameterJdbcTemplate")]),e._v("类是自动配置的,并且你可以将它们"),a("code",[e._v("@Autowire")]),e._v("直接放入你自己的 bean 中,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final JdbcTemplate jdbcTemplate;\n\n public MyBean(JdbcTemplate jdbcTemplate) {\n this.jdbcTemplate = jdbcTemplate;\n }\n\n public void doSomething() {\n this.jdbcTemplate ...\n }\n\n}\n\n")])])]),a("p",[e._v("你可以使用"),a("code",[e._v("spring.jdbc.template.*")]),e._v("属性自定义模板的一些属性,如下例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.jdbc.template.max-rows=500\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring:\n jdbc:\n template:\n max-rows: 500\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[a("code",[e._v("NamedParameterJdbcTemplate")]),e._v("在幕后重用相同的"),a("code",[e._v("JdbcTemplate")]),e._v("实例。"),a("br"),e._v("如果定义了多个"),a("code",[e._v("JdbcTemplate")]),e._v("且不存在主要候选项,则"),a("code",[e._v("NamedParameterJdbcTemplate")]),e._v("不会自动配置。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h3",{attrs:{id:"_1-3-jpa-和-spring-数据-jpa"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-jpa-和-spring-数据-jpa"}},[e._v("#")]),e._v(" 1.3. JPA 和 Spring 数据 JPA")]),e._v(" "),a("p",[e._v("Java Persistence API 是一种标准技术,它允许你将对象“映射”到关系数据库。"),a("code",[e._v("spring-boot-starter-data-jpa")]),e._v(" POM 提供了一种快速入门的方法。它提供了以下关键依赖项:")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("Hibernate:最流行的实现方式之一 JPA。")])]),e._v(" "),a("li",[a("p",[e._v("Spring 数据 JPA:帮助你实现基于 JPA 的存储库。")])]),e._v(" "),a("li",[a("p",[e._v("Spring ORM:来自 Spring 框架的核心 ORM 支持。")])])]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("在这里,我们不会对 JPA 或"),a("a",{attrs:{href:"https://spring.io/projects/spring-data",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data"),a("OutboundLink")],1),e._v("进行过多的详细说明。"),a("br"),e._v("你可以按照"),a("a",{attrs:{href:"https://spring.io/guides/gs/accessing-data-jpa/",target:"_blank",rel:"noopener noreferrer"}},[e._v("“Accessing Data with JPA”"),a("OutboundLink")],1),e._v("中的"),a("a",{attrs:{href:"https://spring.io/guides/gs/accessing-data-jpa/",target:"_blank",rel:"noopener noreferrer"}},[e._v("“Accessing Data with JPA”"),a("OutboundLink")],1),e._v("指南,并阅读"),a("a",{attrs:{href:"https://spring.io/projects/spring-data-jpa",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data JPA"),a("OutboundLink")],1),e._v("和"),a("a",{attrs:{href:"https://hibernate.org/orm/documentation/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Hibernate"),a("OutboundLink")],1),e._v("参考文档。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-3-1-实体类别"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-1-实体类别"}},[e._v("#")]),e._v(" 1.3.1.实体类别")]),e._v(" "),a("p",[e._v("传统上, JPA“实体”类是在"),a("code",[e._v("persistence.xml")]),e._v("文件中指定的。在 Spring 启动时,这个文件不是必需的,而是使用“实体扫描”。默认情况下,将搜索主配置类下面的所有包(注释为"),a("code",[e._v("@EnableAutoConfiguration")]),e._v("或"),a("code",[e._v("@SpringBootApplication")]),e._v("的包)。")]),e._v(" "),a("p",[e._v("任何带有"),a("code",[e._v("@Entity")]),e._v("、"),a("code",[e._v("@Embeddable")]),e._v("或"),a("code",[e._v("@MappedSuperclass")]),e._v("注释的类都将被考虑。典型的实体类类似于以下示例:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import java.io.Serializable;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\npublic class City implements Serializable {\n\n @Id\n @GeneratedValue\n private Long id;\n\n @Column(nullable = false)\n private String name;\n\n @Column(nullable = false)\n private String state;\n\n // ... additional members, often include @OneToMany mappings\n\n protected City() {\n // no-args constructor required by JPA spec\n // this one is protected since it should not be used directly\n }\n\n public City(String name, String state) {\n this.name = name;\n this.state = state;\n }\n\n public String getName() {\n return this.name;\n }\n\n public String getState() {\n return this.state;\n }\n\n // ... etc\n\n}\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你可以使用"),a("code",[e._v("@EntityScan")]),e._v("注释自定义实体扫描位置。"),a("br"),e._v("参见“"),a("RouterLink",{attrs:{to:"/spring-boot/howto.html#howto.data-access.separate-entity-definitions-from-spring-configuration"}},[e._v("howto.html")]),e._v("”操作方法。")],1)])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-3-2-spring-数据-jpa-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-2-spring-数据-jpa-存储库"}},[e._v("#")]),e._v(" 1.3.2. Spring 数据 JPA 存储库")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-jpa",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data JPA"),a("OutboundLink")],1),e._v("存储库是你可以定义以访问数据的接口。 JPA 查询是根据你的方法名称自动创建的。例如,一个"),a("code",[e._v("CityRepository")]),e._v("接口可以声明一个"),a("code",[e._v("findAllByState(String state)")]),e._v("方法来查找给定状态下的所有城市。")]),e._v(" "),a("p",[e._v("对于更复杂的查询,你可以使用 Spring data 的["),a("code",[e._v("Query")]),e._v("](https://DOCS. Spring.io/ Spring-data/ JPA/DOCS/2.6.2/api/org/springframework/data/ JPA/repository/query.html)注释来注释你的方法。")]),e._v(" "),a("p",[e._v("Spring 数据存储库通常扩展自["),a("code",[e._v("Repository")]),e._v("](https://DOCS. Spring.io/ Spring-data/commons/DOCS/2.6.2/api/org/springframework/data/repository/repository.html)或["),a("code",[e._v("CrudRepository")]),e._v("(https://DOCS. Spring.io/ Spring-data/commons/DOCS/2.6.2/api/org/springframFramework/data/depository.html)接口。如果使用自动配置,那么存储库将从包含主配置类(用"),a("code",[e._v("@EnableAutoConfiguration")]),e._v("或"),a("code",[e._v("@SpringBootApplication")]),e._v("注释的类)的包中向下搜索。")]),e._v(" "),a("p",[e._v("下面的示例显示了典型的 Spring 数据存储库接口定义:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.Repository;\n\npublic interface CityRepository extends Repository {\n\n Page findAll(Pageable pageable);\n\n City findByNameAndStateAllIgnoringCase(String name, String state);\n\n}\n\n")])])]),a("p",[e._v("Spring 数据 JPA 存储库支持三种不同的引导模式:默认模式、延迟模式和惰性模式。要启用延迟引导或延迟引导,将"),a("code",[e._v("spring.data.jpa.repositories.bootstrap-mode")]),e._v("属性分别设置为"),a("code",[e._v("deferred")]),e._v("或"),a("code",[e._v("lazy")]),e._v("。当使用延迟或延迟引导时,自动配置的"),a("code",[e._v("EntityManagerFactoryBuilder")]),e._v("将使用上下文的"),a("code",[e._v("AsyncTaskExecutor")]),e._v("(如果有的话)作为引导执行器。如果存在多个选项,将使用名为"),a("code",[e._v("applicationTaskExecutor")]),e._v("的选项。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("当使用延迟引导或延迟引导时,请确保在应用程序上下文引导阶段之后推迟对 JPA 基础架构的任何访问。"),a("br"),e._v("你可以使用"),a("code",[e._v("SmartInitializingSingleton")]),e._v("来调用任何需要 JPA 基础架构的初始化。"),a("br"),e._v("对于创建为 Spring bean 的 JPA 组件(例如转换器),使用"),a("code",[e._v("ObjectProvider")]),e._v("来延迟依赖关系的解决(如果有的话)。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("我们几乎没有触及 Spring 数据 JPA 的表面。"),a("br"),e._v("有关完整的详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/jpa/docs/2.6.2/reference/html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data JPA reference documentation"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-3-3-spring-数据影响存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-3-spring-数据影响存储库"}},[e._v("#")]),e._v(" 1.3.3. Spring 数据影响存储库")]),e._v(" "),a("p",[e._v("如果"),a("a",{attrs:{href:"https://spring.io/projects/spring-data-envers",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Envers"),a("OutboundLink")],1),e._v("可用, JPA 存储库将自动配置为支持典型的 Envers 查询。")]),e._v(" "),a("p",[e._v("要使用 Spring data envers,请确保你的存储库从"),a("code",[e._v("RevisionRepository")]),e._v("扩展,如下例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.Repository;\nimport org.springframework.data.repository.history.RevisionRepository;\n\npublic interface CountryRepository extends RevisionRepository, Repository {\n\n Page findAll(Pageable pageable);\n\n}\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关更多详细信息,请查看"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/envers/docs/2.6.2/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Envers reference documentation"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-3-4-创建和删除-jpa-数据库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-4-创建和删除-jpa-数据库"}},[e._v("#")]),e._v(" 1.3.4.创建和删除 JPA 数据库")]),e._v(" "),a("p",[e._v("默认情况下,如果使用嵌入式数据库(H2、HSQL 或 Derby),将自动创建 JPA 数据库"),a("strong",[e._v("只有")]),e._v("。你可以使用"),a("code",[e._v("spring.jpa.*")]),e._v("属性显式地配置 JPA 设置。例如,要创建和删除表格,你可以在"),a("code",[e._v("application.properties")]),e._v("中添加以下行:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.jpa.hibernate.ddl-auto=create-drop\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n jpa:\n hibernate.ddl-auto: "create-drop"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Hibernate 自己的内部属性名称(如果你能更好地记住它的话)是"),a("code",[e._v("hibernate.hbm2ddl.auto")]),e._v(","),a("br"),e._v(",你可以将其与其他 Hibernate 本机属性一起设置,通过使用"),a("code",[e._v("spring.jpa.properties.*")]),e._v("(前缀在将其添加到实体管理器之前被剥离)。"),a("br"),e._v("下面的一行显示了为 Hibernate 设置 JPA 属性的示例:")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.jpa.properties.hibernate[globally_quoted_identifiers]=true\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n jpa:\n properties:\n hibernate:\n "globally_quoted_identifiers": "true"\n')])])]),a("p",[e._v("前面示例中的行将"),a("code",[e._v("hibernate.globally_quoted_identifiers")]),e._v("属性的值"),a("code",[e._v("true")]),e._v("传递给 Hibernate 实体管理器。")]),e._v(" "),a("p",[e._v("默认情况下,DDL 的执行(或验证)被推迟到"),a("code",[e._v("ApplicationContext")]),e._v("已经开始时。还有一个"),a("code",[e._v("spring.jpa.generate-ddl")]),e._v("标志,但如果 Hibernate 自动配置是活动的,则不会使用它,因为"),a("code",[e._v("ddl-auto")]),e._v("设置的粒度更细。")]),e._v(" "),a("h4",{attrs:{id:"_1-3-5-在视图中打开-entitymanager"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-5-在视图中打开-entitymanager"}},[e._v("#")]),e._v(" 1.3.5.在视图中打开 EntityManager")]),e._v(" "),a("p",[e._v("如果你正在运行一个 Web 应用程序, Spring 默认引导寄存器["),a("code",[e._v("OpenEntityManagerInViewInterceptor")]),e._v("](https://DOCS. Spring.io/ Spring-framework/DOCS/5.3.16/javadoc-api/org/springframework/orm/ JPA/support/openentitymanagerinviewinterceptor.html)应用“Opentitymanager in view”模式,以允许在 Web 视图中进行延迟加载。如果不希望发生这种行为,则应在"),a("code",[e._v("application.properties")]),e._v("中将"),a("code",[e._v("spring.jpa.open-in-view")]),e._v("设置为"),a("code",[e._v("false")]),e._v("。")]),e._v(" "),a("h3",{attrs:{id:"_1-4-spring-数据-jdbc"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-4-spring-数据-jdbc"}},[e._v("#")]),e._v(" 1.4. Spring 数据 JDBC")]),e._v(" "),a("p",[e._v("Spring 数据包括对 JDBC 的存储库支持,并且将为"),a("code",[e._v("CrudRepository")]),e._v("上的方法自动生成 SQL。对于更高级的查询,提供了"),a("code",[e._v("@Query")]),e._v("注释。")]),e._v(" "),a("p",[e._v("Spring 当必要的依赖关系在 Classpath 上时,启动将自动配置 Spring 数据的 JDBC 存储库。它们可以通过对"),a("code",[e._v("spring-boot-starter-data-jdbc")]),e._v("的单一依赖添加到你的项目中。如果有必要,你可以通过向应用程序添加"),a("code",[e._v("@EnableJdbcRepositories")]),e._v("注释或"),a("code",[e._v("JdbcConfiguration")]),e._v("子类来控制 Spring 数据 JDBC 的配置。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关 Spring 数据 JDBC 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/jdbc/docs/2.3.2/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h3",{attrs:{id:"_1-5-使用-h2-的网络控制台"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-5-使用-h2-的网络控制台"}},[e._v("#")]),e._v(" 1.5.使用 H2 的网络控制台")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://www.h2database.com",target:"_blank",rel:"noopener noreferrer"}},[e._v("H2 数据库"),a("OutboundLink")],1),e._v("提供了一个"),a("a",{attrs:{href:"https://www.h2database.com/html/quickstart.html#h2_console",target:"_blank",rel:"noopener noreferrer"}},[e._v("基于浏览器的控制台"),a("OutboundLink")],1),e._v(", Spring 引导可以为你自动配置。当满足以下条件时,控制台将自动配置:")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("你正在开发一个基于 Servlet 的 Web 应用程序。")])]),e._v(" "),a("li",[a("p",[a("code",[e._v("com.h2database:h2")]),e._v("在 Classpath 上。")])]),e._v(" "),a("li",[a("p",[e._v("你使用的是"),a("RouterLink",{attrs:{to:"/spring-boot/using.html#using.devtools"}},[e._v("Spring Boot’s developer tools")]),e._v("。")],1)])]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果你不使用 Spring Boot 的开发工具,但仍想使用 H2 的控制台,则可以配置"),a("code",[e._v("spring.h2.console.enabled")]),e._v("属性,其值为"),a("code",[e._v("true")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("H2 控制台仅用于开发过程中,因此你应该注意确保在生产过程中不将"),a("code",[e._v("spring.h2.console.enabled")]),e._v("设置为"),a("code",[e._v("true")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-5-1-改变-h2-控制台的路径"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-5-1-改变-h2-控制台的路径"}},[e._v("#")]),e._v(" 1.5.1.改变 H2 控制台的路径")]),e._v(" "),a("p",[e._v("默认情况下,控制台位于"),a("code",[e._v("/h2-console")]),e._v("。你可以使用"),a("code",[e._v("spring.h2.console.path")]),e._v("属性来定制控制台的路径。")]),e._v(" "),a("h3",{attrs:{id:"_1-6-使用-jooq"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-6-使用-jooq"}},[e._v("#")]),e._v(" 1.6.使用 Jooq")]),e._v(" "),a("p",[e._v("Jooq 面向对象查询("),a("a",{attrs:{href:"https://www.jooq.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("jOOQ"),a("OutboundLink")],1),e._v(")是"),a("a",{attrs:{href:"https://www.datageekery.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("数据极客"),a("OutboundLink")],1),e._v("中的一种流行产品,它从你的数据库生成 Java 代码,并允许你通过其 Fluent API 构建类型安全的 SQL 查询。商业版和开放源代码版都可以与 Spring boot 一起使用。")]),e._v(" "),a("h4",{attrs:{id:"_1-6-1-代码生成"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-6-1-代码生成"}},[e._v("#")]),e._v(" 1.6.1.代码生成")]),e._v(" "),a("p",[e._v("为了使用 Jooq 类型安全查询,你需要从数据库模式生成 Java 类。你可以按照"),a("a",{attrs:{href:"https://www.jooq.org/doc/3.14.15/manual-single-page/#jooq-in-7-steps-step3",target:"_blank",rel:"noopener noreferrer"}},[e._v("Jooq 用户手册"),a("OutboundLink")],1),e._v("中的说明进行操作。如果你使用"),a("code",[e._v("jooq-codegen-maven")]),e._v("插件,并且还使用"),a("code",[e._v("spring-boot-starter-parent")]),e._v("“parent POM”,则可以安全地省略该插件的"),a("code",[e._v("")]),e._v("标记。你还可以使用 Spring 引导定义的版本变量(例如"),a("code",[e._v("h2.version")]),e._v(")来声明插件的数据库依赖关系。下面的清单展示了一个示例:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("\n org.jooq\n jooq-codegen-maven\n \n ...\n \n \n \n com.h2database\n h2\n ${h2.version}\n \n \n \n \n org.h2.Driver\n jdbc:h2:~/yourdatabase\n \n \n ...\n \n \n\n")])])]),a("h4",{attrs:{id:"_1-6-2-使用-dslcontext"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-6-2-使用-dslcontext"}},[e._v("#")]),e._v(" 1.6.2.使用 DSLContext")]),e._v(" "),a("p",[e._v("由 Jooq 提供的 Fluent API 是通过"),a("code",[e._v("org.jooq.DSLContext")]),e._v("接口启动的。 Spring 引导自动将"),a("code",[e._v("DSLContext")]),e._v("配置为 Spring Bean,并将其连接到你的应用程序"),a("code",[e._v("DataSource")]),e._v("。要使用"),a("code",[e._v("DSLContext")]),e._v(",你可以注入它,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import java.util.GregorianCalendar;\nimport java.util.List;\n\nimport org.jooq.DSLContext;\n\nimport org.springframework.stereotype.Component;\n\nimport static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;\n\n@Component\npublic class MyBean {\n\n private final DSLContext create;\n\n public MyBean(DSLContext dslContext) {\n this.create = dslContext;\n }\n\n}\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Jooq 手册倾向于使用一个名为"),a("code",[e._v("create")]),e._v("的变量来保存"),a("code",[e._v("DSLContext")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("然后,你可以使用"),a("code",[e._v("DSLContext")]),e._v("来构造查询,如下例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("public List authorsBornAfter1980() {\n return this.create.selectFrom(AUTHOR)\n .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))\n .fetch(AUTHOR.DATE_OF_BIRTH);\n\n")])])]),a("h4",{attrs:{id:"_1-6-3-jooq-sql-方言"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-6-3-jooq-sql-方言"}},[e._v("#")]),e._v(" 1.6.3.Jooq SQL 方言")]),e._v(" "),a("p",[e._v("除非已经配置了"),a("code",[e._v("spring.jooq.sql-dialect")]),e._v("属性,否则 Spring boot 将确定要用于数据源的 SQL 方言。如果 Spring boot 无法检测到该方言,则使用"),a("code",[e._v("DEFAULT")]),e._v("。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Spring 启动只能自动配置由开源版本的 Jooq 支持的方言。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-6-4-定制-jooq"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-6-4-定制-jooq"}},[e._v("#")]),e._v(" 1.6.4.定制 Jooq")]),e._v(" "),a("p",[e._v("可以通过定义你自己的"),a("code",[e._v("DefaultConfigurationCustomizer")]),e._v(" Bean 来实现更高级的自定义,该自定义将在创建"),a("code",[e._v("org.jooq.Configuration``@Bean")]),e._v("之前调用。这优先于自动配置所应用的任何内容。")]),e._v(" "),a("p",[e._v("如果你想完全控制 Jooq 配置,还可以创建自己的"),a("code",[e._v("org.jooq.Configuration``@Bean")]),e._v("。")]),e._v(" "),a("h3",{attrs:{id:"_1-7-使用-r2dbc"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-7-使用-r2dbc"}},[e._v("#")]),e._v(" 1.7.使用 R2DBC")]),e._v(" "),a("p",[e._v("反应式关系数据库连接("),a("a",{attrs:{href:"https://r2dbc.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("R2DBC"),a("OutboundLink")],1),e._v(")项目将反应式编程 API 引入到关系数据库中。R2DBC 的"),a("code",[e._v("io.r2dbc.spi.Connection")]),e._v("提供了一种处理非阻塞数据库连接的标准方法。使用"),a("code",[e._v("ConnectionFactory")]),e._v("提供连接,类似于使用 JDBC 提供"),a("code",[e._v("DataSource")]),e._v("。")]),e._v(" "),a("p",[a("code",[e._v("ConnectionFactory")]),e._v("配置由"),a("code",[e._v("spring.r2dbc.*")]),e._v("中的外部配置属性控制。例如,你可以在"),a("code",[e._v("application.properties")]),e._v("中声明以下部分:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.r2dbc.url=r2dbc:postgresql://localhost/test\nspring.r2dbc.username=dbuser\nspring.r2dbc.password=dbpass\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n r2dbc:\n url: "r2dbc:postgresql://localhost/test"\n username: "dbuser"\n password: "dbpass"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你不需要指定驱动程序类名,因为 Spring Boot 从 R2DBC 的连接工厂发现获得驱动程序。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("至少应该提供 URL。"),a("br"),e._v("URL 中指定的信息优先于单个属性,即"),a("code",[e._v("name")]),e._v("、"),a("code",[e._v("username")]),e._v("、"),a("code",[e._v("password")]),e._v("和池选项。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("“how-to”部分包括"),a("RouterLink",{attrs:{to:"/spring-boot/howto.html#howto.data-initialization.using-basic-sql-scripts"}},[e._v("关于如何初始化数据库的一节")]),e._v("。")],1)])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("要自定义由"),a("code",[e._v("ConnectionFactory")]),e._v("创建的连接,即设置在中央数据库配置中不希望(或不能)配置的特定参数,可以使用"),a("code",[e._v("ConnectionFactoryOptionsBuilderCustomizer``@Bean")]),e._v("。下面的示例展示了如何手动重写数据库端口,而其余的选项将从应用程序配置中获取:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import io.r2dbc.spi.ConnectionFactoryOptions;\n\nimport org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration(proxyBeanMethods = false)\npublic class MyR2dbcConfiguration {\n\n @Bean\n public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {\n return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);\n }\n\n}\n\n")])])]),a("p",[e._v("以下示例展示了如何设置一些 PostgreSQL 连接选项:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import java.util.HashMap;\nimport java.util.Map;\n\nimport io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;\n\nimport org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration(proxyBeanMethods = false)\npublic class MyPostgresR2dbcConfiguration {\n\n @Bean\n public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {\n Map options = new HashMap<>();\n options.put("lock_timeout", "30s");\n options.put("statement_timeout", "60s");\n return (builder) -> builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);\n }\n\n}\n\n')])])]),a("p",[e._v("当"),a("code",[e._v("ConnectionFactory")]),e._v(" Bean 可用时,常规的 JDBC"),a("code",[e._v("DataSource")]),e._v("自动配置将退出。如果你希望保留 JDBC"),a("code",[e._v("DataSource")]),e._v("自动配置,并且对在反应性应用程序中使用阻塞 JDBC API 的风险感到满意,那么在应用程序中的"),a("code",[e._v("@Import(DataSourceAutoConfiguration.class)")]),e._v("类上添加"),a("code",[e._v("@Import(DataSourceAutoConfiguration.class)")]),e._v("以重新启用它。")]),e._v(" "),a("h4",{attrs:{id:"_1-7-1-嵌入式数据库支持"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-7-1-嵌入式数据库支持"}},[e._v("#")]),e._v(" 1.7.1.嵌入式数据库支持")]),e._v(" "),a("p",[e._v("与"),a("RouterLink",{attrs:{to:"/spring-boot/features.html#data.sql.datasource.embedded"}},[e._v("JDBC 支持")]),e._v("类似, Spring 引导可以自动配置嵌入式数据库以用于被动使用。你不需要提供任何连接 URL。你只需要对要使用的嵌入式数据库包含一个构建依赖项,如以下示例所示:")],1),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("\n io.r2dbc\n r2dbc-h2\n runtime\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果在测试中使用此功能,你可能会注意到,无论你使用的应用程序上下文的数量如何,整个测试套件都可以重用相同的数据库,如果你想确保每个上下文都有一个单独的嵌入式数据库,"),a("br"),e._v(",你应该将"),a("code",[e._v("spring.r2dbc.generate-unique-name")]),e._v("设置为"),a("code",[e._v("true")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_1-7-2-使用-databaseclient"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-7-2-使用-databaseclient"}},[e._v("#")]),e._v(" 1.7.2.使用 DatabaseClient")]),e._v(" "),a("p",[e._v("a"),a("code",[e._v("DatabaseClient")]),e._v(" Bean 是自动配置的,你可以"),a("code",[e._v("@Autowire")]),e._v("它直接进入你自己的 bean 中,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import java.util.Map;\n\nimport reactor.core.publisher.Flux;\n\nimport org.springframework.r2dbc.core.DatabaseClient;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final DatabaseClient databaseClient;\n\n public MyBean(DatabaseClient databaseClient) {\n this.databaseClient = databaseClient;\n }\n\n // ...\n\n public Flux> someMethod() {\n return this.databaseClient.sql("select * from user").fetch().all();\n }\n\n}\n\n')])])]),a("h4",{attrs:{id:"_1-7-3-spring-数据-r2dbc-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-7-3-spring-数据-r2dbc-存储库"}},[e._v("#")]),e._v(" 1.7.3. Spring 数据 R2DBC 存储库")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-r2dbc",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data R2DBC"),a("OutboundLink")],1),e._v("存储库是你可以定义以访问数据的接口。查询是根据你的方法名称自动创建的。例如,"),a("code",[e._v("CityRepository")]),e._v("接口可以声明一个"),a("code",[e._v("findAllByState(String state)")]),e._v("方法来查找给定州中的所有城市。")]),e._v(" "),a("p",[e._v("对于更复杂的查询,你可以使用 Spring data 的["),a("code",[e._v("Query")]),e._v("](https://DOCS. Spring.io/ Spring-data/r2dbc/DOCS/1.4.2/api/org/springframework/data/r2dbc/repository/query.html)注释来注释你的方法。")]),e._v(" "),a("p",[e._v("Spring 数据存储库通常扩展自["),a("code",[e._v("Repository")]),e._v("](https://DOCS. Spring.io/ Spring-data/commons/DOCS/2.6.2/api/org/springframework/data/repository/repository.html)或["),a("code",[e._v("CrudRepository")]),e._v("](https://DOCS. Spring.io/ Spring-data/commons/DOCS/2.6.2/api/org/springframform/data/repository.html)接口。如果使用自动配置,那么存储库将从包含主配置类(用"),a("code",[e._v("@EnableAutoConfiguration")]),e._v("或"),a("code",[e._v("@SpringBootApplication")]),e._v("注释的类)的包中向下搜索。")]),e._v(" "),a("p",[e._v("下面的示例显示了典型的 Spring 数据存储库接口定义:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import reactor.core.publisher.Mono;\n\nimport org.springframework.data.repository.Repository;\n\npublic interface CityRepository extends Repository {\n\n Mono findByNameAndStateAllIgnoringCase(String name, String state);\n\n}\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("我们几乎没有触及 Spring 数据 R2DBC 的表面。有关完整的详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/r2dbc/docs/1.4.2/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data R2DBC reference documentation"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h2",{attrs:{id:"_2-使用-nosql-技术"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-使用-nosql-技术"}},[e._v("#")]),e._v(" 2. 使用 NoSQL 技术")]),e._v(" "),a("hr"),e._v(" "),a("p",[e._v("Spring Data 提供了帮助你访问各种 NoSQL 技术的附加项目,这些技术包括:")]),e._v(" "),a("ul",[a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-mongodb",target:"_blank",rel:"noopener noreferrer"}},[e._v("MongoDB"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-neo4j",target:"_blank",rel:"noopener noreferrer"}},[e._v("Neo4J"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-elasticsearch",target:"_blank",rel:"noopener noreferrer"}},[e._v("Elasticsearch"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-redis",target:"_blank",rel:"noopener noreferrer"}},[e._v("Redis"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-gemfire",target:"_blank",rel:"noopener noreferrer"}},[e._v("GemFire"),a("OutboundLink")],1),e._v("或"),a("a",{attrs:{href:"https://spring.io/projects/spring-data-geode",target:"_blank",rel:"noopener noreferrer"}},[e._v("Geode"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-cassandra",target:"_blank",rel:"noopener noreferrer"}},[e._v("Cassandra"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-couchbase",target:"_blank",rel:"noopener noreferrer"}},[e._v("Couchbase"),a("OutboundLink")],1)])]),e._v(" "),a("li",[a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-ldap",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDAP"),a("OutboundLink")],1)])])]),e._v(" "),a("p",[e._v("Spring Boot 为 Redis、MongoDB、NEO4J、SOLR、ElasticSearch、Cassandra、CouchBase、LDAP 和 InfluxDB 提供了自动配置。你可以使用其他项目,但必须自己配置它们。请参阅"),a("a",{attrs:{href:"https://spring.io/projects/spring-data",target:"_blank",rel:"noopener noreferrer"}},[e._v("spring.io/projects/spring-data"),a("OutboundLink")],1),e._v("上的相应参考文档。")]),e._v(" "),a("h3",{attrs:{id:"_2-1-雷迪斯"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-1-雷迪斯"}},[e._v("#")]),e._v(" 2.1.雷迪斯")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://redis.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Redis"),a("OutboundLink")],1),e._v("是一个缓存、消息代理和功能丰富的键值存储。 Spring Boot 为"),a("a",{attrs:{href:"https://github.com/lettuce-io/lettuce-core/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Lettuce"),a("OutboundLink")],1),e._v("和"),a("a",{attrs:{href:"https://github.com/xetorthio/jedis/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Jedis"),a("OutboundLink")],1),e._v("客户端库以及"),a("a",{attrs:{href:"https://github.com/spring-projects/spring-data-redis",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Redis"),a("OutboundLink")],1),e._v("在它们之上提供的抽象提供了基本的自动配置。")]),e._v(" "),a("p",[e._v("有一个"),a("code",[e._v("spring-boot-starter-data-redis")]),e._v("“starter”,可以方便地收集依赖项。默认情况下,它使用"),a("a",{attrs:{href:"https://github.com/lettuce-io/lettuce-core/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Lettuce"),a("OutboundLink")],1),e._v("。该启动器同时处理传统应用程序和被动应用程序。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("我们还提供了"),a("code",[e._v("spring-boot-starter-data-redis-reactive")]),e._v("“starter”,以便与具有反应性支持的其他存储保持一致。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_2-1-1-连接到-redis"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-1-1-连接到-redis"}},[e._v("#")]),e._v(" 2.1.1.连接到 Redis")]),e._v(" "),a("p",[e._v("可以像其他任何实例 Spring Bean 一样,注入一个自动配置的"),a("code",[e._v("RedisConnectionFactory")]),e._v("、"),a("code",[e._v("StringRedisTemplate")]),e._v("或 vanilla"),a("code",[e._v("RedisTemplate")]),e._v("实例。默认情况下,实例尝试连接到"),a("code",[e._v("localhost:6379")]),e._v("的 Redis 服务器。下面的清单显示了这样的示例 Bean:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import org.springframework.data.redis.core.StringRedisTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final StringRedisTemplate template;\n\n public MyBean(StringRedisTemplate template) {\n this.template = template;\n }\n\n // ...\n\n public Boolean someMethod() {\n return this.template.hasKey("spring");\n }\n\n}\n\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你还可以注册任意数量的实现"),a("code",[e._v("LettuceClientConfigurationBuilderCustomizer")]),e._v("的 bean 以进行更高级的自定义。"),a("code",[e._v("ClientResources")]),e._v("也可以使用"),a("code",[e._v("ClientResourcesBuilderCustomizer")]),e._v("进行自定义。"),a("br"),e._v("如果你使用 JEDIS,"),a("code",[e._v("JedisClientConfigurationBuilderCustomizer")]),e._v("也是可用的。"),a("br"),e._v("或者,你可以注册类型"),a("code",[e._v("RedisStandaloneConfiguration")]),e._v("的 Bean,"),a("code",[e._v("RedisSentinelConfiguration")]),e._v(",或"),a("code",[e._v("RedisClusterConfiguration")]),e._v("以完全控制配置。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("如果你添加了你自己的"),a("code",[e._v("@Bean")]),e._v("的任何自动配置的类型,它将替换默认的类型(除了在"),a("code",[e._v("RedisTemplate")]),e._v("的情况下,当排除是基于 Bean 名称时,"),a("code",[e._v("redisTemplate")]),e._v(",而不是其类型)。")]),e._v(" "),a("p",[e._v("默认情况下,如果"),a("code",[e._v("commons-pool2")]),e._v("在 Classpath 上,则自动配置池连接工厂。")]),e._v(" "),a("h3",{attrs:{id:"_2-2-mongodb"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-2-mongodb"}},[e._v("#")]),e._v(" 2.2.MongoDB")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://www.mongodb.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("MongoDB"),a("OutboundLink")],1),e._v("是一个开源的 NoSQL 文档数据库,它使用类似 JSON 的模式,而不是传统的基于表的关系数据。 Spring Boot 为使用 MongoDB 提供了几种便利,包括"),a("code",[e._v("spring-boot-starter-data-mongodb")]),e._v("和"),a("code",[e._v("spring-boot-starter-data-mongodb-reactive")]),e._v("“starters”。")]),e._v(" "),a("h4",{attrs:{id:"_2-2-1-连接到-mongodb-数据库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-2-1-连接到-mongodb-数据库"}},[e._v("#")]),e._v(" 2.2.1.连接到 MongoDB 数据库")]),e._v(" "),a("p",[e._v("要访问 MongoDB 数据库,你可以插入一个自动配置的"),a("code",[e._v("org.springframework.data.mongodb.MongoDatabaseFactory")]),e._v("。默认情况下,实例尝试以"),a("code",[e._v("mongodb://localhost/test")]),e._v("连接到 MongoDB 服务器。下面的示例展示了如何连接到 MongoDB 数据库:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport org.bson.Document;\n\nimport org.springframework.data.mongodb.MongoDatabaseFactory;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final MongoDatabaseFactory mongo;\n\n public MyBean(MongoDatabaseFactory mongo) {\n this.mongo = mongo;\n }\n\n // ...\n\n public MongoCollection someMethod() {\n MongoDatabase db = this.mongo.getMongoDatabase();\n return db.getCollection("users");\n }\n\n}\n\n')])])]),a("p",[e._v("如果你已经定义了自己的"),a("code",[e._v("MongoClient")]),e._v(",它将被用来自动配置一个合适的"),a("code",[e._v("MongoDatabaseFactory")]),e._v("。")]),e._v(" "),a("p",[e._v("自动配置的"),a("code",[e._v("MongoClient")]),e._v("是使用"),a("code",[e._v("MongoClientSettings")]),e._v(" Bean 创建的。如果你已经定义了自己的"),a("code",[e._v("MongoClientSettings")]),e._v(",则将不加修改地使用它,并且"),a("code",[e._v("spring.data.mongodb")]),e._v("属性将被忽略。否则,将自动配置"),a("code",[e._v("MongoClientSettings")]),e._v(",并将"),a("code",[e._v("spring.data.mongodb")]),e._v("属性应用到它。在这两种情况下,都可以声明一个或多个"),a("code",[e._v("MongoClientSettingsBuilderCustomizer")]),e._v("bean 来微调"),a("code",[e._v("MongoClientSettings")]),e._v("配置。将按顺序调用每个函数,并使用用于构建"),a("code",[e._v("MongoClientSettings")]),e._v("的"),a("code",[e._v("MongoClientSettings.Builder")]),e._v("。")]),e._v(" "),a("p",[e._v("你可以设置"),a("code",[e._v("spring.data.mongodb.uri")]),e._v("属性来更改 URL 并配置其他设置,例如"),a("em",[e._v("复制集")]),e._v(",如下例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.mongodb.uri=mongodb://user:[email protected]:12345,mongo2.example.com:23456/test\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n data:\n mongodb:\n uri: "mongodb://user:[email protected]:12345,mongo2.example.com:23456/test"\n')])])]),a("p",[e._v("或者,你可以使用离散属性指定连接细节。例如,你可以在"),a("code",[e._v("application.properties")]),e._v("中声明以下设置:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.mongodb.host=mongoserver.example.com\nspring.data.mongodb.port=27017\nspring.data.mongodb.database=test\nspring.data.mongodb.username=user\nspring.data.mongodb.password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n data:\n mongodb:\n host: "mongoserver.example.com"\n port: 27017\n database: "test"\n username: "user"\n password: "secret"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果没有指定"),a("code",[e._v("spring.data.mongodb.port")]),e._v(",则使用"),a("code",[e._v("27017")]),e._v("的默认值。"),a("br"),e._v("你可以从前面显示的示例中删除这一行。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v('如果不使用 Spring dataMongoDB,则可以注入 Bean 而不是使用如果你想完全控制建立 MongoDB 连接,还可以声明你自己的 Bean。')])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果你使用的是反应式驱动程序,则 SSL 需要 Netty。"),a("br"),e._v("如果 Netty 可用,并且使用的工厂尚未自定义,则自动配置将自动配置该工厂。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_2-2-2-mongotemplate"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-2-2-mongotemplate"}},[e._v("#")]),e._v(" 2.2.2.MongoTemplate")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-mongodb",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data MongoDB"),a("OutboundLink")],1),e._v("提供了一个["),a("code",[e._v("MongoTemplate")]),e._v("](https://DOCS. Spring.io/ Spring-data/MongoDB/DOCS/3.3.2/api/org/SpringFramework/data/MongoDB/Core/MongoTemplate.html)类,其设计与 Spring 的"),a("code",[e._v("JdbcTemplate")]),e._v("非常相似。与"),a("code",[e._v("JdbcTemplate")]),e._v("一样, Spring 引导自动配置一个 Bean 以供你插入模板,如下所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import com.mongodb.client.MongoCollection;\nimport org.bson.Document;\n\nimport org.springframework.data.mongodb.core.MongoTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final MongoTemplate mongoTemplate;\n\n public MyBean(MongoTemplate mongoTemplate) {\n this.mongoTemplate = mongoTemplate;\n }\n\n // ...\n\n public MongoCollection someMethod() {\n return this.mongoTemplate.getCollection("users");\n }\n\n}\n\n')])])]),a("p",[e._v("有关完整的详细信息,请参见["),a("code",[e._v("MongoOperations")]),e._v("Javadoc](https://DOCS. Spring.io/ Spring-data/MongoDB/DOCS/3.3.2/api/org/SpringFramework/data/MongoDB/Core/MongoOperations.html)。")]),e._v(" "),a("h4",{attrs:{id:"_2-2-3-spring-数据-mongodb-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-2-3-spring-数据-mongodb-存储库"}},[e._v("#")]),e._v(" 2.2.3. Spring 数据 MongoDB 存储库")]),e._v(" "),a("p",[e._v("Spring 数据包括对 MongoDB 的存储库支持。与前面讨论的 JPA 存储库一样,基本原理是基于方法名自动构造查询。")]),e._v(" "),a("p",[e._v("实际上, Spring 数据 JPA 和 Spring 数据 MongoDB 共享相同的公共基础设施。你可以使用前面的 JPA 示例,假设"),a("code",[e._v("City")]),e._v("现在是一个 MongoDB 数据类,而不是 JPA "),a("code",[e._v("@Entity")]),e._v(",它以相同的方式工作,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.Repository;\n\npublic interface CityRepository extends Repository {\n\n Page findAll(Pageable pageable);\n\n City findByNameAndStateAllIgnoringCase(String name, String state);\n\n}\n\n")])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("你可以使用"),a("code",[e._v("@EntityScan")]),e._v("注释自定义文档扫描位置。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关 Spring Data MongoDB 的完整详细信息,包括其丰富的对象映射技术,请参见其"),a("a",{attrs:{href:"https://spring.io/projects/spring-data-mongodb",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_2-2-4-嵌入式-mongo"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-2-4-嵌入式-mongo"}},[e._v("#")]),e._v(" 2.2.4.嵌入式 Mongo")]),e._v(" "),a("p",[e._v("Spring Boot 提供了"),a("a",{attrs:{href:"https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo",target:"_blank",rel:"noopener noreferrer"}},[e._v("嵌入式 Mongo"),a("OutboundLink")],1),e._v("的自动配置。要在 Spring 引导应用程序中使用它,请在"),a("code",[e._v("de.flapdoodle.embed:de.flapdoodle.embed.mongo")]),e._v("上添加一个依赖项,并将"),a("code",[e._v("spring.mongodb.embedded.version")]),e._v("属性设置为与你的应用程序将在生产中使用的 MongoDB 版本匹配。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("默认的下载配置允许访问[Embedded Mongo 的"),a("code",[e._v("Version")]),e._v("类]中列出的大多数版本(https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/blob/de.flapdoodle.embed.mongo-3.0.0/SRC/main/java/de/flapdoodle/embed/mongo/do/dismission/version.java)"),a("br"),e._v("在试图下载服务器时,配置一个不可访问的版本将导致一个错误。"),a("br"),e._v("这样的错误可以通过定义一个适当配置的"),a("code",[e._v("DownloadConfigBuilderCustomizer")]),e._v(" Bean 来纠正。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("可以通过设置"),a("code",[e._v("spring.data.mongodb.port")]),e._v("属性来配置 Mongo 监听的端口。要使用随机分配的空闲端口,请使用 0。由"),a("code",[e._v("MongoAutoConfiguration")]),e._v("创建的"),a("code",[e._v("MongoClient")]),e._v("被自动配置为使用随机分配的端口。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果不配置自定义端口,则默认情况下,嵌入式支持使用随机端口(而不是 27017)。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("如果在 Classpath 上有 SLF4J,则 Mongo 产生的输出将自动路由到名为"),a("code",[e._v("org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo")]),e._v("的记录器。")]),e._v(" "),a("p",[e._v("你可以声明自己的"),a("code",[e._v("IMongodConfig")]),e._v("和"),a("code",[e._v("IRuntimeConfig")]),e._v("bean 来控制 Mongo 实例的配置和日志路由。可以通过声明"),a("code",[e._v("DownloadConfigBuilderCustomizer")]),e._v(" Bean 来定制下载配置。")]),e._v(" "),a("h3",{attrs:{id:"_2-3-neo4j"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-3-neo4j"}},[e._v("#")]),e._v(" 2.3.NEO4J")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://neo4j.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Neo4j"),a("OutboundLink")],1),e._v("是一个开源的 NoSQL 图数据库,它使用由第一类关系连接的节点的丰富数据模型,与传统的 RDBMS 方法相比,该模型更适合于连接的大数据。 Spring Boot 为使用 NEO4j 提供了几种便利,包括"),a("code",[e._v("spring-boot-starter-data-neo4j")]),e._v("“starter”。")]),e._v(" "),a("h4",{attrs:{id:"_2-3-1-连接到-neo4j-数据库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-3-1-连接到-neo4j-数据库"}},[e._v("#")]),e._v(" 2.3.1.连接到 NEO4J 数据库")]),e._v(" "),a("p",[e._v("要访问 NEO4J 服务器,可以插入自动配置的"),a("code",[e._v("org.neo4j.driver.Driver")]),e._v("。默认情况下,实例尝试使用 Bolt 协议连接到 NEO4J 服务器"),a("code",[e._v("localhost:7687")]),e._v("。下面的示例展示了如何注入一个 NEO4j"),a("code",[e._v("Driver")]),e._v(",它使你能够访问"),a("code",[e._v("Session")]),e._v(",其中包括:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import org.neo4j.driver.Driver;\nimport org.neo4j.driver.Session;\nimport org.neo4j.driver.Values;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final Driver driver;\n\n public MyBean(Driver driver) {\n this.driver = driver;\n }\n\n // ...\n\n public String someMethod(String message) {\n try (Session session = this.driver.session()) {\n return session.writeTransaction((transaction) -> transaction\n .run("CREATE (a:Greeting) SET a.message = $message RETURN a.message + \', from node \' + id(a)",\n Values.parameters("message", message))\n .single().get(0).asString());\n }\n }\n\n}\n\n')])])]),a("p",[e._v("你可以使用"),a("code",[e._v("spring.neo4j.*")]),e._v("属性配置驱动程序的各个方面。下面的示例展示了如何配置要使用的 URI 和凭据:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.neo4j.uri=bolt://my-server:7687\nspring.neo4j.authentication.username=neo4j\nspring.neo4j.authentication.password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n neo4j:\n uri: "bolt://my-server:7687"\n authentication:\n username: "neo4j"\n password: "secret"\n')])])]),a("p",[e._v("自动配置的"),a("code",[e._v("Driver")]),e._v("是使用"),a("code",[e._v("ConfigBuilder")]),e._v("创建的。要微调其配置,请声明一个或多个"),a("code",[e._v("ConfigBuilderCustomizer")]),e._v("bean。每个都将按顺序调用"),a("code",[e._v("ConfigBuilder")]),e._v(",这是用来构建"),a("code",[e._v("Driver")]),e._v("的。")]),e._v(" "),a("h4",{attrs:{id:"_2-3-2-spring-数据-neo4j-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-3-2-spring-数据-neo4j-存储库"}},[e._v("#")]),e._v(" 2.3.2. Spring 数据 NEO4J 存储库")]),e._v(" "),a("p",[e._v("Spring 数据存储库包括对 NEO4j 的支持。有关 Spring 数据 NEO4j 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/neo4j/docs/6.2.2/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")]),e._v(" "),a("p",[e._v("Spring 数据 NEO4J 与 Spring 数据共享公共基础设施 JPA,就像许多其他 Spring 数据模块所做的那样。你可以从前面的 JPA 示例中将"),a("code",[e._v("City")]),e._v("定义为 Spring 数据 NEO4j"),a("code",[e._v("@Node")]),e._v(",而不是 JPA "),a("code",[e._v("@Entity")]),e._v(",并且存储库抽象以相同的方式工作,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import java.util.Optional;\n\nimport org.springframework.data.neo4j.repository.Neo4jRepository;\n\npublic interface CityRepository extends Neo4jRepository {\n\n Optional findOneByNameAndState(String name, String state);\n\n}\n\n")])])]),a("p",[a("code",[e._v("spring-boot-starter-data-neo4j")]),e._v("“starter”支持存储库和事务管理。 Spring 使用"),a("code",[e._v("Neo4jTemplate")]),e._v("或"),a("code",[e._v("ReactiveNeo4jTemplate")]),e._v("bean,启动同时支持经典的和反应的 NEO4j 存储库。 Classpath 上的项目反应器是可用的时,反应方式也是自动配置的。")]),e._v(" "),a("p",[e._v("你可以通过在"),a("code",[e._v("@Configuration")]),e._v("- Bean 上分别使用"),a("code",[e._v("@EnableNeo4jRepositories")]),e._v("和"),a("code",[e._v("@EntityScan")]),e._v("来定制查找存储库和实体的位置。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("在使用反应样式的应用程序中,a"),a("code",[e._v("ReactiveTransactionManager")]),e._v("不是自动配置的。"),a("br"),e._v("要启用事务管理,必须在你的配置中定义以下 Bean:"),a("br"),a("br"),a("code",[e._v("
import org.neo4j.driver.Driver;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;

@Configuration(proxyBeanMethods = false)
public class MyNeo4jConfiguration {

@Bean
public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}

}

")])])])]),e._v(" "),a("tbody")]),e._v(" "),a("h3",{attrs:{id:"_2-4-solr"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-4-solr"}},[e._v("#")]),e._v(" 2.4.SOLR")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://lucene.apache.org/solr/",target:"_blank",rel:"noopener noreferrer"}},[e._v("阿帕奇 SOLR"),a("OutboundLink")],1),e._v("是一个搜索引擎。 Spring 启动为 SOLR5 的客户端库提供了基本的自动配置。")]),e._v(" "),a("h4",{attrs:{id:"_2-4-1-连接到-solr"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-4-1-连接到-solr"}},[e._v("#")]),e._v(" 2.4.1.连接到 SOLR")]),e._v(" "),a("p",[e._v("你可以注入一个自动配置的"),a("code",[e._v("SolrClient")]),e._v("实例,就像你将注入任何其他 Spring Bean 实例一样。默认情况下,实例尝试连接到"),a("code",[e._v("[localhost:8983/solr](http://localhost:8983/solr)")]),e._v("的服务器。以下示例显示了如何注入 SOLR Bean:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('import java.io.IOException;\n\nimport org.apache.solr.client.solrj.SolrClient;\nimport org.apache.solr.client.solrj.SolrServerException;\nimport org.apache.solr.client.solrj.response.SolrPingResponse;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final SolrClient solr;\n\n public MyBean(SolrClient solr) {\n this.solr = solr;\n }\n\n // ...\n\n public SolrPingResponse someMethod() throws SolrServerException, IOException {\n return this.solr.ping("users");\n }\n\n}\n\n')])])]),a("p",[e._v("如果你添加你自己的"),a("code",[e._v("@Bean")]),e._v("类型的"),a("code",[e._v("SolrClient")]),e._v(",它将替换缺省值。")]),e._v(" "),a("h3",{attrs:{id:"_2-5-elasticsearch"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-5-elasticsearch"}},[e._v("#")]),e._v(" 2.5.Elasticsearch")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://www.elastic.co/products/elasticsearch",target:"_blank",rel:"noopener noreferrer"}},[e._v("Elasticsearch"),a("OutboundLink")],1),e._v("是一个开源、分布式、RESTful 搜索和分析引擎。 Spring Boot 为 ElasticSearch 客户端提供了基本的自动配置。")]),e._v(" "),a("p",[e._v("Spring Boot 支持多个客户端:")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("官方的 Java“low level”和“high level”REST 客户端")])]),e._v(" "),a("li",[a("p",[e._v("Spring Data ElasticSearch 提供的"),a("code",[e._v("ReactiveElasticsearchClient")])])])]),e._v(" "),a("p",[e._v("Spring Boot 提供了一个专用的“starter”,"),a("code",[e._v("spring-boot-starter-data-elasticsearch")]),e._v("。")]),e._v(" "),a("h4",{attrs:{id:"_2-5-1-使用-rest-客户端连接到-elasticsearch"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-5-1-使用-rest-客户端连接到-elasticsearch"}},[e._v("#")]),e._v(" 2.5.1.使用 REST 客户端连接到 ElasticSearch")]),e._v(" "),a("p",[e._v("ElasticSearch 附带"),a("a",{attrs:{href:"https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("两个不同的 REST 客户机"),a("OutboundLink")],1),e._v(",你可以使用它来查询集群:“低级别”客户端和“高级别”客户端。 Spring Boot 提供对“高级别”客户端的支持,该客户端附带"),a("code",[e._v("org.elasticsearch.client:elasticsearch-rest-high-level-client")]),e._v("。此外, Spring Boot 基于 Spring Framework 的"),a("code",[e._v("WebClient")]),e._v("提供对反应式客户端的支持,该客户端附带"),a("code",[e._v("org.springframework.data:spring-data-elasticsearch")]),e._v("。默认情况下,客户机将以"),a("code",[e._v("[localhost:9200](http://localhost:9200)")]),e._v("为目标。你可以使用"),a("code",[e._v("spring.elasticsearch.*")]),e._v("属性来进一步优化客户机的配置方式,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.elasticsearch.uris=https://search.example.com:9200\nspring.elasticsearch.socket-timeout=10s\nspring.elasticsearch.username=user\nspring.elasticsearch.password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n elasticsearch:\n uris: "https://search.example.com:9200"\n socket-timeout: "10s"\n username: "user"\n password: "secret"\n')])])]),a("h5",{attrs:{id:"使用-resthiglevelclient-连接到-elasticsearch"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用-resthiglevelclient-连接到-elasticsearch"}},[e._v("#")]),e._v(" 使用 resthigLevelClient 连接到 ElasticSearch####")]),e._v(" "),a("p",[e._v("如果在 Classpath 上有"),a("code",[e._v("elasticsearch-rest-high-level-client")]),e._v(", Spring 引导将自动配置并注册一个"),a("code",[e._v("RestHighLevelClient")]),e._v(" Bean。除了前面描述的属性之外,要微调"),a("code",[e._v("RestHighLevelClient")]),e._v(",你可以注册任意数量的 bean,这些 bean 实现"),a("code",[e._v("RestClientBuilderCustomizer")]),e._v("以进行更高级的自定义。要完全控制其注册,请定义"),a("code",[e._v("RestClientBuilder")]),e._v(" Bean。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果你的应用程序需要访问“low level”"),a("code",[e._v("RestClient")]),e._v(",则可以通过在自动配置的"),a("code",[e._v("client.getLowLevelClient()")]),e._v("上调用"),a("code",[e._v("client.getLowLevelClient()")]),e._v("来获得它。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("此外,如果"),a("code",[e._v("elasticsearch-rest-client-sniffer")]),e._v("在 Classpath 上,则"),a("code",[e._v("Sniffer")]),e._v("被自动配置为自动从正在运行的 ElasticSearch 集群中发现节点,并将它们设置在"),a("code",[e._v("RestHighLevelClient")]),e._v(" Bean 上。你可以进一步调整"),a("code",[e._v("Sniffer")]),e._v("的配置方式,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.elasticsearch.restclient.sniffer.interval=10m\nspring.elasticsearch.restclient.sniffer.delay-after-failure=30s\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n elasticsearch:\n restclient:\n sniffer:\n interval: "10m"\n delay-after-failure: "30s"\n')])])]),a("h5",{attrs:{id:"使用-reactiveelasticsearchclient-连接到-elasticsearch"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用-reactiveelasticsearchclient-连接到-elasticsearch"}},[e._v("#")]),e._v(" 使用 ReactiveElasticSearchClient 连接到 ElasticSearch####")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://spring.io/projects/spring-data-elasticsearch",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Elasticsearch"),a("OutboundLink")],1),e._v("提供"),a("code",[e._v("ReactiveElasticsearchClient")]),e._v("用于以反应方式查询 ElasticSearch 实例。它是建立在 WebFlux 的"),a("code",[e._v("WebClient")]),e._v("之上的,因此"),a("code",[e._v("spring-boot-starter-elasticsearch")]),e._v("和"),a("code",[e._v("spring-boot-starter-webflux")]),e._v("依赖关系都有助于启用此支持。")]),e._v(" "),a("p",[e._v("默认情况下, Spring 启动将自动配置并注册"),a("code",[e._v("ReactiveElasticsearchClient")]),e._v("。除了前面描述的属性外,"),a("code",[e._v("spring.elasticsearch.webclient.*")]),e._v("属性还可用于配置特定于反应性的设置,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.elasticsearch.webclient.max-in-memory-size=1MB\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n elasticsearch:\n webclient:\n max-in-memory-size: "1MB"\n')])])]),a("p",[e._v("如果"),a("code",[e._v("spring.elasticsearch.")]),a("strong",[e._v("和"),a("code",[e._v("spring.elasticsearch.webclient.")])]),e._v(" 配置属性不够,并且希望完全控制客户机配置,则可以注册一个自定义的"),a("code",[e._v("ClientConfiguration")]),e._v(" Bean。")]),e._v(" "),a("h4",{attrs:{id:"_2-5-2-通过使用-spring-数据-连接到-elasticsearch"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-5-2-通过使用-spring-数据-连接到-elasticsearch"}},[e._v("#")]),e._v(" 2.5.2.通过使用 Spring 数据 #### 连接到 ElasticSearch")]),e._v(" "),a("p",[e._v("要连接到 ElasticSearch,必须定义一个"),a("code",[e._v("RestHighLevelClient")]),e._v(" Bean,通过 Spring 引导自动配置,或者由应用程序手动提供(请参见前面的部分)。有了这种配置,"),a("code",[e._v("ElasticsearchRestTemplate")]),e._v("可以像任何其他 Spring Bean 一样注入,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final ElasticsearchRestTemplate template;\n\n public MyBean(ElasticsearchRestTemplate template) {\n this.template = template;\n }\n\n // ...\n\n public boolean someMethod(String id) {\n return this.template.exists(id, User.class);\n }\n\n}\n\n")])])]),a("p",[e._v("在存在"),a("code",[e._v("spring-data-elasticsearch")]),e._v("和使用"),a("code",[e._v("WebClient")]),e._v("所需的依赖关系(通常为"),a("code",[e._v("spring-boot-starter-webflux")]),e._v(")的情况下, Spring 引导还可以自动配置一个"),a("RouterLink",{attrs:{to:"/spring-boot/features.html#data.nosql.elasticsearch.connecting-using-rest.webclient"}},[e._v("ReactiveElasticSearchClient")]),e._v("和一个"),a("code",[e._v("ReactiveElasticsearchTemplate")]),e._v("作为 bean。他们相当于其他 REST 客户的被动反应。")],1),e._v(" "),a("h4",{attrs:{id:"_2-5-3-spring-数据弹性搜索库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-5-3-spring-数据弹性搜索库"}},[e._v("#")]),e._v(" 2.5.3. Spring 数据弹性搜索库")]),e._v(" "),a("p",[e._v("Spring 数据包括对 ElasticSearch 的存储库支持。与前面讨论的 JPA 存储库一样,基本原则是根据方法名自动为你构造查询。")]),e._v(" "),a("p",[e._v("实际上, Spring 数据 JPA 和 Spring 数据弹性搜索共享相同的公共基础设施。你可以以前面的 JPA 为例,假设"),a("code",[e._v("City")]),e._v("现在是一个 ElasticSearch"),a("code",[e._v("@Document")]),e._v("类,而不是 JPA "),a("code",[e._v("@Entity")]),e._v(",它以同样的方式工作。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关 Spring 数据 ElasticSearch 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("Spring Boot 使用"),a("code",[e._v("ElasticsearchRestTemplate")]),e._v("或"),a("code",[e._v("ReactiveElasticsearchTemplate")]),e._v("bean,支持经典的和反应的 Elasticsearch 存储库。考虑到存在所需的依赖关系,这些 bean 很可能是通过 Spring 引导自动配置的。")]),e._v(" "),a("p",[e._v("如果你希望使用自己的模板来支持 ElasticSearch 存储库,则可以添加自己的"),a("code",[e._v("ElasticsearchRestTemplate")]),e._v("或"),a("code",[e._v("ElasticsearchOperations``@Bean")]),e._v(",只要它的名称为"),a("code",[e._v('"elasticsearchTemplate"')]),e._v("。这同样适用于"),a("code",[e._v("ReactiveElasticsearchTemplate")]),e._v("和"),a("code",[e._v("ReactiveElasticsearchOperations")]),e._v(",其 Bean 名称为"),a("code",[e._v('"reactiveElasticsearchTemplate"')]),e._v("。")]),e._v(" "),a("p",[e._v("你可以选择使用以下属性禁用存储库支持:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.elasticsearch.repositories.enabled=false\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring:\n data:\n elasticsearch:\n repositories:\n enabled: false\n")])])]),a("h3",{attrs:{id:"_2-6-卡桑德拉"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-6-卡桑德拉"}},[e._v("#")]),e._v(" 2.6.卡桑德拉")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://cassandra.apache.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Cassandra"),a("OutboundLink")],1),e._v("是一个开源的分布式数据库管理系统,旨在处理跨许多商品服务器的大量数据。 Spring Boot 提供了对 Cassandra 的自动配置以及"),a("a",{attrs:{href:"https://github.com/spring-projects/spring-data-cassandra",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Cassandra"),a("OutboundLink")],1),e._v("在其之上提供的抽象。有一个"),a("code",[e._v("spring-boot-starter-data-cassandra")]),e._v("“starter”可以方便地收集依赖项。")]),e._v(" "),a("h4",{attrs:{id:"_2-6-1-连接到-cassandra"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-6-1-连接到-cassandra"}},[e._v("#")]),e._v(" 2.6.1.连接到 Cassandra")]),e._v(" "),a("p",[e._v("你可以插入一个自动配置的"),a("code",[e._v("CassandraTemplate")]),e._v("或一个 Cassandra"),a("code",[e._v("CqlSession")]),e._v("实例,就像你使用任何其他 Spring Bean 实例一样。"),a("code",[e._v("spring.data.cassandra.*")]),e._v("属性可用于自定义连接。通常,你提供"),a("code",[e._v("keyspace-name")]),e._v("和"),a("code",[e._v("contact-points")]),e._v("以及本地数据中心名称,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.cassandra.keyspace-name=mykeyspace\nspring.data.cassandra.contact-points=cassandrahost1:9042,cassandrahost2:9042\nspring.data.cassandra.local-datacenter=datacenter1\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n data:\n cassandra:\n keyspace-name: "mykeyspace"\n contact-points: "cassandrahost1:9042,cassandrahost2:9042"\n local-datacenter: "datacenter1"\n')])])]),a("p",[e._v("如果你的所有联系点的端口都是相同的,那么你可以使用快捷方式,并且只指定主机名,如下例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.cassandra.keyspace-name=mykeyspace\nspring.data.cassandra.contact-points=cassandrahost1,cassandrahost2\nspring.data.cassandra.local-datacenter=datacenter1\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n data:\n cassandra:\n keyspace-name: "mykeyspace"\n contact-points: "cassandrahost1,cassandrahost2"\n local-datacenter: "datacenter1"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("这两个示例与端口默认设置"),a("code",[e._v("9042")]),e._v("相同。"),a("br"),e._v("如果需要配置端口,请使用"),a("code",[e._v("spring.data.cassandra.port")]),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Cassandra 驱动程序有自己的配置基础结构在 Classpath 的根位置加载"),a("code",[e._v("application.conf")]),e._v("。"),a("br"),a("br"),e._v(" Spring boot 默认情况下不会查找这样的文件,但是可以使用"),a("code",[e._v("spring.data.cassandra.config")]),e._v("加载一个文件。"),a("br"),e._v("如果一个属性在"),a("code",[e._v("spring.data.cassandra.*")]),e._v("和配置文件中都存在,"),a("code",[e._v("spring.data.cassandra.*")]),e._v("中的值优先。"),a("br"),a("br"),e._v("对于更高级的驱动程序自定义,你可以注册任意数量的实现"),a("code",[e._v("DriverConfigLoaderBuilderCustomizer")]),e._v("的 bean。"),a("br"),a("code",[e._v("CqlSession")]),e._v("可以使用类型为"),a("code",[e._v("CqlSessionBuilderCustomizer")]),e._v("的 Bean 进行自定义。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("如果使用"),a("code",[e._v("CqlSessionBuilder")]),e._v("创建多个"),a("code",[e._v("CqlSession")]),e._v("bean,请记住构建器是可变的,因此请确保为每个会话注入一个新的副本。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("下面的代码清单展示了如何注入 Cassandra Bean:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.data.cassandra.core.CassandraTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final CassandraTemplate template;\n\n public MyBean(CassandraTemplate template) {\n this.template = template;\n }\n\n // ...\n\n public long someMethod() {\n return this.template.count(User.class);\n }\n\n}\n\n")])])]),a("p",[e._v("如果你添加你自己的"),a("code",[e._v("@Bean")]),e._v("类型的"),a("code",[e._v("CassandraTemplate")]),e._v(",它将替换缺省值。")]),e._v(" "),a("h4",{attrs:{id:"_2-6-2-spring-数据卡桑德拉存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-6-2-spring-数据卡桑德拉存储库"}},[e._v("#")]),e._v(" 2.6.2. Spring 数据卡桑德拉存储库")]),e._v(" "),a("p",[e._v("Spring 数据包括对 Cassandra 的基本存储库支持。目前,这比前面讨论的 JPA 存储库更加有限,并且需要用"),a("code",[e._v("@Query")]),e._v("注释查找方法。")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("有关 Spring 数据 Cassandra 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/cassandra/docs/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h3",{attrs:{id:"_2-7-couchbase"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-7-couchbase"}},[e._v("#")]),e._v(" 2.7.Couchbase")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://www.couchbase.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Couchbase"),a("OutboundLink")],1),e._v("是一个开源的、分布式的、多模型的面向 NoSQL 文档的数据库,它为交互式应用程序进行了优化。 Spring Boot 提供了对 CouchBase 的自动配置以及由"),a("a",{attrs:{href:"https://github.com/spring-projects/spring-data-couchbase",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Couchbase"),a("OutboundLink")],1),e._v("提供的在其之上的抽象。有"),a("code",[e._v("spring-boot-starter-data-couchbase")]),e._v("和"),a("code",[e._v("spring-boot-starter-data-couchbase-reactive")]),e._v("“启动器”,可以方便地收集依赖项。")]),e._v(" "),a("h4",{attrs:{id:"_2-7-1-连接到-couchbase"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-7-1-连接到-couchbase"}},[e._v("#")]),e._v(" 2.7.1.连接到 Couchbase")]),e._v(" "),a("p",[e._v("你可以通过添加 CouchBase SDK 和一些配置来获得"),a("code",[e._v("Cluster")]),e._v("。"),a("code",[e._v("spring.couchbase.*")]),e._v("属性可用于自定义连接。通常,你提供"),a("a",{attrs:{href:"https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0011-connection-string.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("连接字符串"),a("OutboundLink")],1),e._v("、用户名和密码,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.couchbase.connection-string=couchbase://192.168.1.123\nspring.couchbase.username=user\nspring.couchbase.password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n couchbase:\n connection-string: "couchbase://192.168.1.123"\n username: "user"\n password: "secret"\n')])])]),a("p",[e._v("也可以自定义一些"),a("code",[e._v("ClusterEnvironment")]),e._v("设置。例如,以下配置更改了用于打开新的"),a("code",[e._v("Bucket")]),e._v("并启用 SSL 支持的超时时间:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.couchbase.env.timeouts.connect=3s\nspring.couchbase.env.ssl.key-store=/location/of/keystore.jks\nspring.couchbase.env.ssl.key-store-password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n couchbase:\n env:\n timeouts:\n connect: "3s"\n ssl:\n key-store: "/location/of/keystore.jks"\n key-store-password: "secret"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("查看"),a("code",[e._v("spring.couchbase.env.*")]),e._v("属性以获得更多详细信息。"),a("br"),e._v("要获得更多控制权,可以使用一个或多个"),a("code",[e._v("ClusterEnvironmentBuilderCustomizer")]),e._v("bean。")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"_2-7-2-spring-数据-couchbase-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-7-2-spring-数据-couchbase-存储库"}},[e._v("#")]),e._v(" 2.7.2. Spring 数据 CouchBase 存储库")]),e._v(" "),a("p",[e._v("Spring 数据包括对 CouchBase 的存储库支持。有关 Spring Data Couchbase 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/couchbase/docs/4.3.2/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")]),e._v(" "),a("p",[e._v("你可以注入一个自动配置的"),a("code",[e._v("CouchbaseTemplate")]),e._v("实例,就像使用任何其他 Spring Bean 一样,前提是"),a("code",[e._v("CouchbaseClientFactory")]),e._v(" Bean 是可用的。如上所述,当"),a("code",[e._v("Cluster")]),e._v("可用时,并且指定了一个 bucket 名称时,就会发生这种情况:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.data.couchbase.bucket-name=my-bucket\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n data:\n couchbase:\n bucket-name: "my-bucket"\n')])])]),a("p",[e._v("以下示例显示了如何注入"),a("code",[e._v("CouchbaseTemplate")]),e._v(" Bean:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.springframework.data.couchbase.core.CouchbaseTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final CouchbaseTemplate template;\n\n public MyBean(CouchbaseTemplate template) {\n this.template = template;\n }\n\n // ...\n\n public String someMethod() {\n return this.template.getBucketName();\n }\n\n}\n\n")])])]),a("p",[e._v("你可以在自己的配置中定义一些 bean 来覆盖自动配置提供的那些 bean:")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("a"),a("code",[e._v("CouchbaseMappingContext``@Bean")]),e._v(",其名称为"),a("code",[e._v("couchbaseMappingContext")]),e._v("。")])]),e._v(" "),a("li",[a("p",[e._v("a"),a("code",[e._v("CustomConversions``@Bean")]),e._v(",其名称为"),a("code",[e._v("couchbaseCustomConversions")]),e._v("。")])]),e._v(" "),a("li",[a("p",[e._v("a"),a("code",[e._v("CouchbaseTemplate``@Bean")]),e._v(",其名称为"),a("code",[e._v("couchbaseTemplate")]),e._v("。")])])]),e._v(" "),a("p",[e._v("为了避免在自己的配置中对这些名称进行硬编码,你可以重用 Spring Data Couchbase 提供的"),a("code",[e._v("BeanNames")]),e._v("。例如,你可以自定义要使用的转换器,如下所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import org.assertj.core.util.Arrays;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.couchbase.config.BeanNames;\nimport org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;\n\n@Configuration(proxyBeanMethods = false)\npublic class MyCouchbaseConfiguration {\n\n @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)\n public CouchbaseCustomConversions myCustomConversions() {\n return new CouchbaseCustomConversions(Arrays.asList(new MyConverter()));\n }\n\n}\n\n")])])]),a("h3",{attrs:{id:"_2-8-ldap"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-8-ldap"}},[e._v("#")]),e._v(" 2.8.LDAP")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDAP"),a("OutboundLink")],1),e._v("(轻量级目录访问协议)是一种开放的、与供应商无关的行业标准应用程序协议,用于在 IP 网络上访问和维护分布式目录信息服务。 Spring 启动提供了对任何兼容的 LDAP 服务器的自动配置,以及对来自"),a("a",{attrs:{href:"https://ldap.com/unboundid-ldap-sdk-for-java/",target:"_blank",rel:"noopener noreferrer"}},[e._v("UnboundID"),a("OutboundLink")],1),e._v("的嵌入式内存中 LDAP 服务器的支持。")]),e._v(" "),a("p",[e._v("LDAP 抽象由"),a("a",{attrs:{href:"https://github.com/spring-projects/spring-data-ldap",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data LDAP"),a("OutboundLink")],1),e._v("提供。有一个"),a("code",[e._v("spring-boot-starter-data-ldap")]),e._v("“starter”,可以方便地收集依赖项。")]),e._v(" "),a("h4",{attrs:{id:"_2-8-1-连接到-ldap-服务器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-8-1-连接到-ldap-服务器"}},[e._v("#")]),e._v(" 2.8.1.连接到 LDAP 服务器")]),e._v(" "),a("p",[e._v("要连接到 LDAP 服务器,请确保声明对"),a("code",[e._v("spring-boot-starter-data-ldap")]),e._v("“starter”或"),a("code",[e._v("spring-ldap-core")]),e._v("的依赖关系,然后在应用程序中声明服务器的 URL。属性,如以下示例所示:")]),e._v(" "),a("p",[e._v("属性")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.ldap.urls=ldap://myserver:1235\nspring.ldap.username=admin\nspring.ldap.password=secret\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n ldap:\n urls: "ldap://myserver:1235"\n username: "admin"\n password: "secret"\n')])])]),a("p",[e._v("如果需要自定义连接设置,可以使用"),a("code",[e._v("spring.ldap.base")]),e._v("和"),a("code",[e._v("spring.ldap.base-environment")]),e._v("属性。")]),e._v(" "),a("p",[e._v("基于这些设置,可以自动配置"),a("code",[e._v("LdapContextSource")]),e._v("。如果"),a("code",[e._v("DirContextAuthenticationStrategy")]),e._v(" Bean 是可用的,则它与自动配置的"),a("code",[e._v("LdapContextSource")]),e._v("相关联。如果你需要自定义它,例如使用"),a("code",[e._v("PooledContextSource")]),e._v(",你仍然可以注入自动配置的"),a("code",[e._v("LdapContextSource")]),e._v("。请确保将你定制的"),a("code",[e._v("ContextSource")]),e._v("标记为"),a("code",[e._v("@Primary")]),e._v(",以便自动配置的"),a("code",[e._v("LdapTemplate")]),e._v("使用它。")]),e._v(" "),a("h4",{attrs:{id:"_2-8-2-spring-数据-ldap-存储库"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-8-2-spring-数据-ldap-存储库"}},[e._v("#")]),e._v(" 2.8.2. Spring 数据 LDAP 存储库")]),e._v(" "),a("p",[e._v("Spring 数据包括对 LDAP 的存储库支持。有关 Spring 数据 LDAP 的完整详细信息,请参见"),a("a",{attrs:{href:"https://docs.spring.io/spring-data/ldap/docs/1.0.x/reference/html/",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考文献"),a("OutboundLink")],1),e._v("。")]),e._v(" "),a("p",[e._v("还可以像使用任何其他 Spring Bean 一样,注入一个自动配置的"),a("code",[e._v("LdapTemplate")]),e._v("实例,如以下示例所示:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("import java.util.List;\n\nimport org.springframework.ldap.core.LdapTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class MyBean {\n\n private final LdapTemplate template;\n\n public MyBean(LdapTemplate template) {\n this.template = template;\n }\n\n // ...\n\n public List someMethod() {\n return this.template.findAll(User.class);\n }\n\n}\n\n")])])]),a("h4",{attrs:{id:"_2-8-3-嵌入式内存-ldap-服务器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-8-3-嵌入式内存-ldap-服务器"}},[e._v("#")]),e._v(" 2.8.3.嵌入式内存 LDAP 服务器")]),e._v(" "),a("p",[e._v("出于测试目的, Spring 引导支持"),a("a",{attrs:{href:"https://ldap.com/unboundid-ldap-sdk-for-java/",target:"_blank",rel:"noopener noreferrer"}},[e._v("UnboundID"),a("OutboundLink")],1),e._v("中的内存中 LDAP 服务器的自动配置。要配置服务器,请向"),a("code",[e._v("com.unboundid:unboundid-ldapsdk")]),e._v("添加一个依赖项,并声明一个"),a("code",[e._v("spring.ldap.embedded.base-dn")]),e._v("属性,如下所示:")]),e._v(" "),a("p",[e._v("Properties")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.ldap.embedded.base-dn=dc=spring,dc=io\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n ldap:\n embedded:\n base-dn: "dc=spring,dc=io"\n')])])]),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("可以定义多个 base-dn 值,但是,由于专有名称通常包含逗号,因此必须使用正确的符号来定义它们。"),a("br"),a("br"),e._v("在 YAML 文件中,可以使用 YAML 列表符号。在属性文件中,必须将索引作为属性名称的一部分包括在内:"),a("br"),a("br"),e._v("属性"),a("br"),a("br"),a("br"),a("br"),e._v("yaml"),a("br"),a("code",[e._v('
spring.ldap.embedded.base-dn:
- "dc=spring,dc=io"
- "dc=pivotal,dc=io"
')])])])]),e._v(" "),a("tbody")]),e._v(" "),a("p",[e._v("默认情况下,服务器从一个随机端口启动,并触发常规的 LDAP 支持。不需要指定"),a("code",[e._v("spring.ldap.urls")]),e._v("属性。")]),e._v(" "),a("p",[e._v("如果在你的 Classpath 上有一个"),a("code",[e._v("schema.ldif")]),e._v("文件,它将用于初始化服务器。如果希望从其他资源加载初始化脚本,还可以使用"),a("code",[e._v("spring.ldap.embedded.ldif")]),e._v("属性。")]),e._v(" "),a("p",[e._v("默认情况下,标准模式用于验证"),a("code",[e._v("LDIF")]),e._v("文件。你可以通过设置"),a("code",[e._v("spring.ldap.embedded.validation.enabled")]),e._v("属性来完全关闭验证。如果你有自定义属性,你可以使用"),a("code",[e._v("spring.ldap.embedded.validation.schema")]),e._v("来定义你的自定义属性类型或对象类。")]),e._v(" "),a("h3",{attrs:{id:"_2-9-影响-b"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-9-影响-b"}},[e._v("#")]),e._v(" 2.9.影响 b")]),e._v(" "),a("p",[a("a",{attrs:{href:"https://www.influxdata.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("InfluxDB"),a("OutboundLink")],1),e._v("是一个开放源代码的时间序列数据库,该数据库经过优化,可用于快速、高可用性地存储和检索操作监控、应用度量、物联网传感器数据和实时分析等领域的时间序列数据。")]),e._v(" "),a("h4",{attrs:{id:"_2-9-1-连接到-influxdb"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-9-1-连接到-influxdb"}},[e._v("#")]),e._v(" 2.9.1.连接到 InfluxDB")]),e._v(" "),a("p",[e._v("Spring 引导自动配置"),a("code",[e._v("InfluxDB")]),e._v("实例,前提是"),a("code",[e._v("influxdb-java")]),e._v("客户端在 Classpath 上并且设置了数据库的 URL,如以下示例所示:")]),e._v(" "),a("p",[e._v("Properties")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("spring.influx.url=https://172.0.0.1:8086\n")])])]),a("p",[e._v("Yaml")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('spring:\n influx:\n url: "https://172.0.0.1:8086"\n')])])]),a("p",[e._v("如果到 InfluxDB 的连接需要用户和密码,则可以相应地设置"),a("code",[e._v("spring.influx.user")]),e._v("和"),a("code",[e._v("spring.influx.password")]),e._v("属性。")]),e._v(" "),a("p",[e._v("InfluxDB 依赖于 OkHTTP。如果你需要调优幕后使用的 HTTP 客户端"),a("code",[e._v("InfluxDB")]),e._v(",则可以注册一个"),a("code",[e._v("InfluxDbOkHttpClientBuilderProvider")]),e._v(" Bean。")]),e._v(" "),a("p",[e._v("如果需要对配置进行更多控制,可以考虑注册"),a("code",[e._v("InfluxDbCustomizer")]),e._v(" Bean。")]),e._v(" "),a("h2",{attrs:{id:"_3-接下来要读什么"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_3-接下来要读什么"}},[e._v("#")]),e._v(" 3. 接下来要读什么?")]),e._v(" "),a("hr"),e._v(" "),a("p",[e._v("你现在应该对如何在各种数据技术中使用 Spring 引导有了一种感觉。从这里,你可以了解 Spring boot 对各种"),a("RouterLink",{attrs:{to:"/spring-boot/messaging.html#messaging"}},[e._v("消息传递技术")]),e._v("的支持,以及如何在应用程序中启用它们。")],1)])}),[],!1,null,null,null);t.default=n.exports}}]);