Spring社區的一個頂級工程,主要用於簡化數據(關係型&非關係型)訪問,若是咱們使用Spring Data來開發程序的話,那麼能夠省去不少低級別的數據訪問操做,如編寫數據查詢語句、DAO類等,咱們僅須要編寫一些抽象接口並定義相關操做便可,Spring會在運行期間的時候建立代理實例來實現咱們接口中定義的操做。html
Spring Data擁有不少子項目,除了Spring Data Jpa外,還有以下子項目。java
Spring Data Commonsmysql
Spring Data MongoDBgit
Spring Data Redisgithub
Spring Data Solrweb
Spring Data Gemfirespring
Spring Data RESTsql
Spring Data Neo4j數據庫
Spring Data Jpa是Spring Data的一個子項目,主要用於簡化數據訪問層的實現,使用Spring Data Jpa能夠輕鬆實現增刪改查、分頁、排序等。apache
以下所示:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-data-jpa-example</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.4.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.7</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
其中,spring-boot-starter-parent會加載Spring Boot應用所需的全部默認配置;
spring-boot-starter-data-jpa會下載全部Spring Data Jpa所需的依賴;
添加spring-boot-starter-web是由於咱們的工程是一個Web應用;
另外咱們的數據庫是mysql,因此還須要mysql-connector-java依賴;
因爲使用了緩存,因此再添加一個spring-boot-starter-cache依賴;
package com.example.domain; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQuery; @Entity @NamedQuery(name = "User.findByName", query = "select name,address from User u where u.name=?1") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id long id; @Column(name = "name") String name; @Column(name = "address") String address; 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 getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
其它沒啥好說的,注意下這裏的@NamedQuery註解,大體意思就是讓咱們在Repository接口中定義的findByName方法不使用默認的查詢實現,取而代之的是使用這條自定義的查詢語句去查詢,若是這裏沒有標註的話,會使用默認實現的。
這裏將編寫兩個Repository接口,僅僅用於示例,實際中能夠合併成一個:
UserJpaRepository
package com.example.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.example.domain.User; public interface UserJpaRepository extends JpaRepository<User,Long> { }
這裏的UserJpaRepository接口實現了JpaRepository接口;
實際上JpaRepository實現了PagingAndSortingRepository接口,PagingAndSortingRepository接口實現了CrudRepository接口,CrudRepository接口實現了Repository接口;
簡單說明下:
Repository接口是一個標識接口,裏面是空的;
CrudRepository接口定義了增刪改查方法;
PagingAndSortingRepository接口用於分頁和排序;
因爲JpaRepository接口繼承了以上全部接口,因此擁有它們聲明的全部方法;
另外注意下,以findAll方法爲例,JpaRepository接口返回的是List, PagingAndSortingRepository和CrudRepository返回的是迭代器;
UserRepository
package com.example.repository; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.Param; import com.example.domain.User; public interface UserRepository extends Repository<User, Long> { List<User> findByNameAndAddress(String name, String address); @Query(value = "from User u where u.name=:name") List<User> findByName1(@Param("name") String name); @Query(value = "select * from #{#entityName} u where u.name=?1", nativeQuery = true) List<User> findByName2(String name); List<User> findByName(String name); }
這裏的UserRepository接口主要定義了一些查詢方法;
好比這裏的findByNameAndAddress和findByName方法,咱們是不須要額外定義其它查詢語句就能夠直接執行的,Spring Data Jpa會根據實體類的屬性名字以及方法名自動實現該方法;PS:因爲咱們在實體類中聲明瞭@NamedQuery註解,實際上findByName方法會使用@NamedQuery註解標註的查詢語句去查詢;
另外這裏的findByName1方法使用了HQL語句查詢;
findByName2方法使用了原始的sql語句查詢;
service接口:
package com.example.service; import java.util.List; import com.example.domain.User; public interface IUserService { public List<User> findAll(); public void saveUser(User book); public User findOne(long id); public void delete(long id); public List<User> findByName(String name); }
接口實現類:
package com.example.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.domain.User; import com.example.repository.UserRepository; import com.example.repository.UserJpaRepository; import com.example.service.IUserService; @Service @Transactional public class UserServiceImpl implements IUserService { @Autowired private UserJpaRepository userJpaRepository; @Autowired private UserRepository userRepository; public List<User> findAll() { return userJpaRepository.findAll(); } public List<User> findByName(String name) { List<User> userList1 = userRepository.findByName1(name); List<User> userList2 = userRepository.findByName2(name); List<User> userList3 = userRepository.findByNameAndAddress(name, "3"); System.out.println("userList1:" + userList1); System.out.println("userList2:" + userList2); System.out.println("userList3:" + userList3); return userRepository.findByName(name); } public void saveUser(User book) { userJpaRepository.save(book); } @Cacheable("users") public User findOne(long id) { System.out.println("Cached Pages"); return userJpaRepository.findOne(id); } public void delete(long id) { userJpaRepository.delete(id); } }
這個沒啥好說的,調用Repository接口接口的方法便可。
Controller也沒啥好說的,調用Service便可,注意下這裏的Controller使用@RestController註解來標註,另外URL路徑命名按照RESTful風格來命名;
package com.example.web; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.domain.User; import com.example.service.IUserService; @RestController @RequestMapping(value = "/users") public class UserController { @Autowired private IUserService userService; @RequestMapping(value = "/add/{id}/{name}/{address}") public User addUser(@PathVariable int id, @PathVariable String name, @PathVariable String address) { User user = new User(); user.setId(id); user.setName(name); user.setAddress(address); userService.saveUser(user); return user; } @RequestMapping(value = "/delete/{id}") public void deleteBook(@PathVariable int id) { userService.delete(id); } @RequestMapping(value = "/") public List<User> getBooks() { return userService.findAll(); } @RequestMapping(value = "/{id}") public User getUser(@PathVariable int id) { User user = userService.findOne(id); return user; } @RequestMapping(value = "/search/name/{name}") public List<User> getBookByName(@PathVariable String name) { List<User> users = userService.findByName(name); return users; } }
在application.properties文件中添加以下配置:
spring.jpa.show-sql = true logging.level.org.springframework.data=DEBUG spring.jpa.hibernate.ddl-auto= spring.datasource.url=jdbc:mysql://localhost:3306/demo spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver
若是你使用STS IDE的話,這些屬性配置都會自動提示的,省的去查找。
想查看spring.datasource的配置,能夠參考這個類:DataSourceProperties.java
比較簡單,注意下該類所屬的包級別要大於或等於其它類,以保證其它類的註解能夠被掃描到。
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class SpringDataJpaExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringDataJpaExampleApplication.class, args); } }
啓動main方法,或打成jar包運行;
瀏覽器輸入如下URL,測試便可:
http://localhost:8080/users/
http://localhost:8080/users/add/100/110/111
http://localhost:8080/users/delete/100
http://localhost:8080/users/2
http://localhost:8080/users/search/name/2
https://github.com/peterchenhdu/spring-data-jpa-example
http://docs.spring.io/spring-data/jpa/docs/1.11.0.RELEASE/reference/html/