15.使用SQL數(shù)據(jù)庫
在Spring框架提供了廣泛的支持使用使用SQL數(shù)據(jù)庫序宦,直接JDBC訪問JdbcTemplate來完成“對象關(guān)系映射”技術(shù),比如Hibernate持际。Spring Data提供了更多級別的功能:Repository直接從接口創(chuàng)建實(shí)現(xiàn),并使用約定從方法名稱生成查詢屈张。
15.1配置數(shù)據(jù)源
Java的javax.sql.DataSource接口提供了一種使用數(shù)據(jù)庫連接的標(biāo)準(zhǔn)方法。傳統(tǒng)上,'DataSource'使用URL一些憑證來建立數(shù)據(jù)庫連接。
15.1.1連接到生產(chǎn)數(shù)據(jù)庫
CREATE DATABASE?IF NOT EXISTS `springboot`;
USE `springboot`;
也可以使用池自動配置生產(chǎn)數(shù)據(jù)庫連接?DataSource祝闻。DataSource配置由外部配置屬性控制?spring.datasource.*。例如遗菠,您可以在以下部分聲明以下部分?application.properties:
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
常見問題1
錯(cuò)誤信息:
com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
解決辦法:
在URL最后增加?serverTimezone=UTC联喘。
如下所示:
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
常見問題2
問題描述:MySQL Server 5.7中文亂碼解決辦法
解決辦法:
修改my.ini文件
Windows路徑:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini
Linux路徑:vim /etc/my.cnf
改為:
[client]
......
default-character-set=utf8
[mysql]
......
default-character-set=utf8
......
[mysqld]
character_set_server=utf8
......
重啟服務(wù)
Windows: 控制面板->服務(wù)->MySQL57
Linux: service mysqld restart
15.2?JPA和Spring Data JPA
Java Persistence API是一種標(biāo)準(zhǔn)技術(shù)华蜒,可讓您將對象“映射”到關(guān)系數(shù)據(jù)庫。該spring-boot-starter-data-jpaPOM提供了上手的快捷方式豁遭。它提供以下關(guān)鍵依賴項(xiàng):
Hibernate:最受歡迎的JPA實(shí)現(xiàn)之一叭喜。
Spring Data JPA:使實(shí)現(xiàn)基于JPA的存儲庫變得容易。
Spring ORMs:Spring Framework的核心ORM支持蓖谢。
在pom.xml中增加依賴包:
<!-- JPA Data -->
????????<dependency>
????????????<groupId>org.springframework.boot</groupId>
????????????<artifactId>spring-boot-starter-data-jpa</artifactId>
????????</dependency>
????????<!-- Use MySQL Connector-J -->
????????<dependency>
????????????<groupId>mysql</groupId>
????????????<artifactId>mysql-connector-java</artifactId>
????????</dependency>
15.2.1實(shí)體類
傳統(tǒng)上捂蕴,JPA“實(shí)體”類在persistence.xml文件中指定。使用Spring Boot闪幽,此文件不是必需的启绰,而是使用“實(shí)體掃描”。默認(rèn)情況下沟使,將搜索主配置類(注釋為@EnableAutoConfiguration或者@SpringBootApplication)下的所有包?。
任何類別標(biāo)注了@Entity渊跋,@Embeddable或者@MappedSuperclass被認(rèn)為是實(shí)體類腊嗡。
典型的實(shí)體類類似于以下示例:
package com.example.demo.city;
import java.io.Serializable;
import javax.persistence.*;
/**
?* 城市實(shí)體類
?*
?* @author 大強(qiáng)
?*
?*/
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
// ... additional members, often include @OneToMany mappings
public?City() {
// no-args constructor required by JPA spec
// this one is protected since it shouldn't be used directly
}
public City(String name, String state) {
this.name = name;
this.state = state;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
// ... etc
}
15.2.2 Spring Data JPA存儲庫
Spring Data JPA存儲庫是您可以定義以訪問數(shù)據(jù)的接口。JPA查詢是從您的方法名稱自動創(chuàng)建的拾酝。例如燕少,?CityRepository接口可能會聲明一種findAllByState(String state)方法來查找給定狀態(tài)中的所有城市。
對于更復(fù)雜的查詢蒿囤,您可以使用Spring Data的Query注釋來注釋您的方法?客们。
Spring Data存儲庫通常從Repository或?CrudRepository?接口擴(kuò)展?。如果使用自動配置材诽,則會從包含主配置類(帶有@EnableAutoConfiguration或標(biāo)注的@SpringBootApplication)的包中搜索存儲庫?底挫。
以下示例顯示了典型的Spring Data存儲庫接口定義:
package com.example.demo.city;
import org.springframework.data.repository.CrudRepository;
/**
?* 城市存儲庫
?*
?* @author 大強(qiáng)
?*
?*/
public interface CityRepository extends CrudRepository<City, Long> {
}
15.2.3?Spring Data JPA控制器
Spring Data JPA提供基于注釋的編程模型,其中@Controller和 @RestController組件使用注釋來表達(dá)請求映射脸侥,請求輸入建邓,異常處理等。帶注釋的控制器具有靈活的方法簽名睁枕,不必?cái)U(kuò)展基類官边,也不必實(shí)現(xiàn)特定的接口。
以下示例顯示了由注釋定義的Spring Data控制器定義:
package com.example.demo.city;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
?* 城市控制器
?*
?* @author 大強(qiáng)
?*
?*/
@Controller // 這意味著這個(gè)類是一個(gè)控制器
@RequestMapping(path = "/city") // 這意味著URL從/city開始(在應(yīng)用程序路徑之后)
public class CityController {
@Autowired // 這意味著要得到一個(gè)名為Cityrepository的存儲庫
private CityRepository cityRepository;
/**
?* 根據(jù)主鍵查詢單個(gè)城市
?*
?* @param id
?* @return
?*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public @ResponseBody City getCity(@PathVariable Long id) {
return cityRepository.findById(id).orElse(new City());
}
/**
?* 查詢所有城市列表
?*
?* @return
?*/
@GetMapping(path = "/all")
public @ResponseBody Iterable<City> getAllCitys() {
// 這將返回帶有citys的JSON或XML
return cityRepository.findAll();
}
/**
?* 新增城市
?*
?* @param name
?* @param state
?* @return
?*/
@PostMapping(path = "/add") // 僅映射Post請求
public @ResponseBody String addCity(@RequestParam String name, @RequestParam String state) {
// @responseBody表示返回的是response外遇,而不是視圖名稱
// @requestParam表示它是get或post請求的參數(shù)
City city = new City();
city.setName(name);
city.setState(state);
cityRepository.save(city);
return "新增城市成功";
}
/**
?* 修改城市
?*
?* @param city
?* @return
?*/
@PutMapping(path = "/update") // 僅映射Put請求
public @ResponseBody String updateCity(@RequestBody City city) {
// @responseBody表示返回的是response注簿,而不是視圖名稱
// @requestParam表示它是get或post請求的參數(shù)
cityRepository.save(city);
return "修改城市成功";
}
/**
?* 刪除城市
?*
?* @param id
?* @return
?*/
@DeleteMapping(path = "/{id}") // 僅映射Delete請求
public @ResponseBody String deleteCity(@PathVariable Long id) {
// @responseBody表示返回的是response,而不是視圖名稱
// @requestParam表示它是get或post請求的參數(shù)
City city = new City();
city.setId(id);
cityRepository.delete(city);
return "刪除城市成功";
}
}
如有疑問跳仿,請觀看視頻:https://ke.qq.com/course/428845