從一個helloworld開始java
創建好springboot的項目後mysql
pom.xmlweb
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <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.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.29</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
配置文件spring
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/jpa?useSSL=FALSE&serverTimezone=GMT%2B8 username: root password: root type: com.alibaba.druid.pool.DruidDataSource filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 jpa: hibernate: ddl-auto: update show-sql: true
實體類sql
@Entity @Data @RequiredArgsConstructor @AllArgsConstructor @NoArgsConstructor public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NonNull private String name; @NonNull private String email; }
倉庫文件數據庫
public interface UserRepository extends CrudRepository<User,Long> { }
controllerjson
@RestController public class UserController { @Autowired private UserRepository userRepository; @SuppressWarnings("unchecked") @Transactional @GetMapping("/add") public Result<String> addNewUser(@RequestParam("name") String name,@RequestParam("email") String email) { User user = new User(name,email); userRepository.save(user); return Result.success("添加用戶成功"); } @GetMapping("/all") @SuppressWarnings("unchecked") public Result<Iterable<User>> getAllUsers() { return Result.success(userRepository.findAll()); } @GetMapping("/user") @SuppressWarnings("unchecked") public Result<User> getUser(@RequestParam("id") Long id) { return Result.success(userRepository.findById(id)); } }
也能夠直接用名字查詢springboot
public interface UserAloneRepository extends Repository<User,Long> { List<User> findByName(String name); }
在UserController中添加app
@Autowired private UserAloneRepository userAloneRepository;
@GetMapping("/user/name") @SuppressWarnings("unchecked") public Result<User> getUserByName(@RequestParam("name") String name) { return Result.success(userAloneRepository.findByName(name)); }
jpa的一個好處是能夠不用手工去數據庫建表,一運行就能夠自動建表。spring-boot
若是要分頁和排序
public interface UserPagingAndSortingRepository extends PagingAndSortingRepository<User,Long> { }
Controller中添加
/** * 分頁和排序 * @return */ @SuppressWarnings("unchecked") @GetMapping("/page") public Result<Page<User>> getAllUserByPage() { return Result.success(userPagingAndSortingRepository.findAll( new PageRequest(0,2,new Sort(new Sort.Order(Sort.Direction.ASC,"name"))) )); } /** * 排序 * @return */ @SuppressWarnings("unchecked") @GetMapping("/sort") public Result<Iterable<User>> getAllUserWithSort() { return Result.success(userPagingAndSortingRepository.findAll( new Sort(new Sort.Order(Sort.Direction.ASC,"name")) )); }
咱們來看一下他的整體繼承關係結構圖
其中SimpleJpaRepository是他們全部接口的實現類,而JpaRepository以上其實都是兼容noSql的接口,而只有JpaRepository如下才是對數據庫特有的接口。
而使用的方法也是同樣,只須要用一個自定義接口繼承便可
public interface UserJpaRespository extends JpaRepository<User,Long> { }
jpa有本身的根據方法名的查詢生成器機制,例如以前的UserAloneRepository中的findByName,findBy是固定前綴,Name是屬性名。咱們來看幾個and、or的查詢。
public interface UserAloneRepository extends Repository<User,Long> { List<User> findByName(String name); List<User> findByNameAndEmail(String name,String email); List<User> findByNameOrEmail(String name,String email); }
Controller中的
@SuppressWarnings("unchecked") @GetMapping("/and") public Result<List<User>> getUserByNameAndEmail(@RequestParam("name") String name,@RequestParam("email") String email) { return Result.success(userAloneRepository.findByNameAndEmail(name,email)); } @SuppressWarnings("unchecked") @GetMapping("/or") public Result<List<User>> getUserByNameOrEmail(@RequestParam("name") String name,@RequestParam("email") String email) { return Result.success(userAloneRepository.findByNameOrEmail(name,email)); }
咱們從打印出來的日誌能夠看到
Hibernate: select user0_.id as id1_0_, user0_.email as email2_0_, user0_.name as name3_0_ from user user0_ where user0_.name=? and user0_.email=?
Hibernate: select user0_.id as id1_0_, user0_.email as email2_0_, user0_.name as name3_0_ from user user0_ where user0_.name=? or user0_.email=?
其實就是where語句後面的and和or.
這種and以及or是能夠無限接下去的多條件查詢。如今咱們來看一下去重和取前幾個數據
public interface UserAloneRepository extends Repository<User,Long> { List<User> findByName(String name); List<User> findByNameAndEmail(String name,String email); List<User> findByNameOrEmail(String name,String email); //去重 List<User> findDistinctByName(String name); //查找前2個 List<User> findTop2ByName(String name); }
只要加上Distinct和Top數字就能夠了
如今給User實體類增長兩個字段
@Entity @Data @RequiredArgsConstructor @AllArgsConstructor @NoArgsConstructor public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NonNull private String name; @NonNull private String email; private int age; private boolean sex; }
啓動項目後,數據庫會自動給user表增長上該字段
全部的jpa關鍵字以下
public interface UserAloneRepository extends Repository<User,Long> { List<User> findByName(String name); List<User> findByNameAndEmail(String name,String email); List<User> findByNameOrEmail(String name,String email); //去重 List<User> findDistinctByName(String name); //查找前2個 List<User> findTop2ByName(String name); //查找小於age參數的 List<User> findByAgeBefore(int age); //查找小於age參數的 List<User> findByAgeLessThan(int age); //查找小於等於age參數的 List<User> findByAgeLessThanEqual(int age); //查找大於age參數的 List<User> findByAgeAfter(int age); //查找大於age參數的 List<User> findByAgeGreaterThan(int age); //查找大於等於age參數的 List<User> findByAgeGreaterThanEqual(int age); //查找name爲null的 List<User> findByNameIsNull(); //查找name不爲null的 List<User> findByNameNotNull(); //查找like name的(此處不帶%) List<User> findByNameLike(String name); //查找not like name的(此處不帶%) List<User> findByNameNotLike(String name); //查找like %name(無後綴%) List<User> findByNameStartingWith(String name); //查找like name%(無前綴%) List<User> findByNameEndingWith(String name); //查找like %name% List<User> findByNameContaining(String name); //根據name查找,按照age排序 List<User> findByNameOrderByAgeDesc(String name); //查找不等於age的 List<User> findByAgeNot(int age); //根據age查找在ages集合內的 List<User> findByAgeIn(Set<Integer> ages); //根據age查找不在ages集合內的 List<User> findByAgeNotIn(Set<Integer> ages); //查找sex爲1的 List<User> findBySexTrue(); //查找sex爲0的 List<User> findBySexFalse(); //按照email查找,不區分大小寫 List<User> findByEmailIgnoreCase(String email); //按照name查找總數 long countByName(String name); //按照name刪除 //此處是根據查找出來的id一條一條刪除的,因此在調用的時候必須加事務 long deleteByName(String name); //按照name刪除 //此處是根據查找出來的id一條一條刪除的,因此在調用的時候必須加事務 List<User> removeByName(String name); }
在刪除時必須帶上事務
@Transactional @SuppressWarnings("unchecked") @GetMapping("/delete") public Result<String> deleteByName(@RequestParam("name") String name) { userAloneRepository.deleteByName(name); return Result.success("刪除成功"); } @Transactional @SuppressWarnings("unchecked") @GetMapping("/remove") public Result<List<User>> removeByName(@RequestParam("name") String name) { return Result.success(userAloneRepository.removeByName(name)); }
根據打印的日誌能夠看到實際上是按照id來刪除的
Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_.email as email3_0_, user0_.name as name4_0_, user0_.sex as sex5_0_ from user user0_ where user0_.name=? Hibernate: delete from user where id=? Hibernate: delete from user where id=?