JPA
Spring Data Jpa 介紹
Spring Data JPA是Spring基於Hibernate開發的一個JPA框架。如果用過Hibernate或者MyBatis的話,就會知道對象關係映射(ORM)框架有多麼方便。但是Spring Data JPA框架功能更進一步,爲我們做了 一個數據持久層框架幾乎能做的任何事情。並且提供了基礎的增刪查方法,具體api請看官網https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/。
簡而言之:它提供了默認的簡單的單表增刪查方法,直接可以使用不用具體關心怎麼去寫sql語句的問題,但是這裏修改的功能是默認沒有提供的,需要自己手寫實現。
實踐
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
注意:mysql新驅動類名路徑和舊版本的區別
建庫建表
由於我們使用的spring data jpa 而jpa的底層實現是hibernate,用過hibernate的同學知道 hibernate可以通過實體類逆向創建表,只需要配置一下ddl-auto 就可以
所以我們需要在application.yml配置一下
server:
port: 8989
pring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/device?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
#日誌文件地址
logging:
path: /opt/log/
file: springbootdemo.log
level:
root: INFO
在上面的配置文件中 我們配置了一個數據源跟tomcat端口還有jpa的配置。其中 show-sql: true 代表會在日誌中打印我們操作的sql、
而另外 ddl-auto有四個值可選,分別是
- create 啓動時刪數據庫中的表,然後創建,退出時不刪除數據表
- create-drop 啓動時刪數據庫中的表,然後創建,退出時刪除數據表 如果表不存在報錯
- update 最常用的屬性,第一次加載hibernate時根據model類會自動建立起表的結構(前提是先建立好數據庫),以後加載hibernate時根據 model類自動更新表結構,即使表結構改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到服務器後,表結構是不會被馬上建立起來的,是要等 應用第一次運行起來後纔會。
- validate 項目啓動表結構進行校驗 如果不一致則報錯
但是數據庫還是需要我們創建的,這裏的test數據庫需要你自行創建
類、映射、DAO
類和表映射
/**
* 設備實體類和表的映射
*/
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
@Entity
public class Device implements Serializable {
private static final long serialVersionUID = -1L;
@Id
@GeneratedValue
private Long id;
@Column(name = "request", nullable = true, length = 12)
private String request;//register
@Column(name = "uuid", nullable = true, length = 32)
private String uuid;//cd33-977e-c809-e03a
@Column(name = "brand", nullable = true, length = 15)
private String brand;//jsrz
@Column(name = "app", nullable = true, length = 12)
private String app;//icast
@Column(name = "model", nullable = true, length = 12)
private String model;//t9wan
@Column(name = "version", nullable = true, length = 12)
private String version;//5.1.1
// setting和getting省略
}
dao操作
DAO操作纔是使用過程的核心,這也是它和mybatis不同的地方最大的區別,這裏簡單的操作基本JpaRepository已經實現了,只有一些特殊的操作需要我們手動創建。
/**
* @program: springboot-demo
* @description: dao操作
* @author: Bamboo [email protected]
* @create: 2019-09-07 13:33
**/
public interface DeviceRepository extends JpaRepository<Device, Long> {
/**
* 根據uuid,它會自動根據find後面的屬性名稱作爲表中對應的字段進行查詢
* 因它的方法名命名規則就是find屬性名,當然還有一些默認的是它已經實現的:findAll,findOne等
* @param uuid
* @return
*/
Device findByUuid(String uuid);
/**
*複雜JPA操作 使用@Query()自定義sql語句 根據業務id UId去更新整個實體
* 刪除和更新操作,需要@Modifying和@Transactional註解的支持
* 更新操作中 如果某個字段爲null則不更新,否則更新【注意符號和空格位置】
*
*修改設備信息拼接sql如果不爲空則修改原有數據
* @param model 傳入實體,分別取實體字段進行set
* @return 更新操作返回sql作用條數
*/
@Modifying
@Transactional
@Query("update Device ex set " +
"ex.app = CASE WHEN :#{#model.app} IS NULL THEN ex.app ELSE :#{#model.app} END ," +
"ex.brand = CASE WHEN :#{#model.brand} IS NULL THEN ex.brand ELSE :#{#model.brand} END ," +
"ex.model = CASE WHEN :#{#model.model} IS NULL THEN ex.model ELSE :#{#model.model} END ," +
"ex.request = CASE WHEN :#{#model.request} IS NULL THEN ex.request ELSE :#{#model.request} END ," +
"ex.version = CASE WHEN :#{#model.version} IS NULL THEN ex.version ELSE :#{#model.version} END " +
"where ex.uuid = :#{#model.uuid}")
int updateByuuid(@Param("model") Device model);
}
updateByuuid:方法名命名規則必須操作+擴展
傳入的值需要佔位符#{#model.request} 形參model和屬性組成
業務邏輯層
業務邏輯層的使用和mybatis使用是相同的,直接注入使用相關dao方法即可
service
/**
* 客戶端接口
*/
public interface BambooDubboService {
/**
* 客戶端接口
* @param uuid
*/
Device sayBamboo(String uuid);
void saveDevice(Device device);
}
ServiceImpl
@Service
public class BambooDubboServiceImpl implements BambooDubboService {
@Autowired
private DeviceRepository deviceRepository;
@Override
public Device sayBamboo(String uuid) {
return deviceRepository.findByUuid(uuid);
}
// 如果不存在該uuid的數據則插入新值
@Override
public void saveDevice(Device device) {
Device deviceTmp = deviceRepository.findByUuid(device.getUuid());
if(Objects.nonNull(deviceTmp)){
deviceRepository.updateByuuid(device);
}else {
deviceRepository.save(device);
}
}
}
controller
MVC
import java.util.Objects;
/**
* demo url
* http://localhost:8080
*
* @author bamboo
* @time 2019-6-27
*/
@RestController
@RequestMapping("/devmgr")
public class BambooController {
private Log logger = LogFactory.getLog(BambooController.class);
@Autowired
BambooDubboService bambooDubboService;
/**
* 查詢操作
*/
@GetMapping("/uuid")
public Object find(Model model, String uuid) {
if(Objects.isNull(uuid)){
return "error:null param";
}
return bambooDubboService.sayBamboo(uuid);
}
/**
* 新增和修改操作
*/
@GetMapping("")
public Object get(Model model, Device device) {
if(Objects.isNull(device)){
return "error:null param";
}
bambooDubboService.saveDevice(device);
return "success";
}
}
啓動服務即可發現,數據庫中它會自動創建兩個表。
devic:業務表
hibernate_sequence:自增ID的序列表
通過下面接口我們可以看到已經有數據插入進去了
http://localhost:8080/devmgr?request=register\&uuid=cd33-977e-c809-e03d\&brand=APP\&app=icast\&model=t9wan\&version=5.1.5
源碼
請訪問我的github
https://github.com/BambooZhang/springboot-study