why?
JPA的作用类似于MyBatis,但更加的自动化,在对数据库性能要求不是特别高的时候很方便。
可以避免繁复的JDBC数据库操作代码的编写,提高java持久层开发的效率。
what?
JPA(Java Persistence API)是Sun官方提出的Java持久化规范,用来方便大家操作数据库。
真正干活的可能是Hibernate,TopLink等等实现了JPA规范的不同厂商,默认是Hibernate。
how?
现在就开始学习简单的使用
1. 基础部件介绍
数据库 + 实体类 + Dao接口
2. 数据库结构
3. jpa的jar包依赖配置(Maven)
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
4. JPA的配置
配置文件位置:src/main/resources/application.properties
添加的配置:
# 配置数据源
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 自动更新数据库表结构
spring.jpa.properties.hibernate.hbm2ddl.auto=update
这个根据个人的数据库情况来修改
5. 实体类
package com.how2java.springboot.pojo;
import javax.persistence.*;
/**
* @Author guozhi
* @Date 2019/7/1 11:18
* @Description TODO
*/
@Entity
@Table( name="name")
public class TableTest {
// 表示这是主键
@Id
// 表示这是自增长类型
@GeneratedValue(strategy = GenerationType.IDENTITY)
// 显式设置列名
@Column(name = "id")
private int id;
@Column(name ="value")
private String value;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "TableTest{" +
"id=" + id +
", value='" + value + '\'' +
'}';
}
}
6. DAO接口
package com.how2java.springboot.dao;
import com.how2java.springboot.pojo.TableTest;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
// 继承封装好的jpa方法
public interface TestDAO extends JpaRepository<TableTest, Integer> {
/**
* 简单条件查询
* @param value
* @return
*/
public List<TableTest> findByValue(String value);
}
这里需要做简单的说明
- 继承了JpaRepository,并且提供泛型<Category,Integer> 表示这个是针对Category类的DAO,Integer表示主键是Integer类型。
- JpaRepository 这个接口,提供了CRUD, 分页等等一系列的查询了等自带方法。
下面列举条件查询的方法规范,符合这些规范就可以不用自己去实现方法,而让框架帮你实现。
7. 测试代码
package com.how2java.springboot.web;
import com.how2java.springboot.dao.TestDAO;
import com.how2java.springboot.pojo.TableTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author guozhi
* @Date 2019/7/1 16:14
* @Description TODO
*/
@Controller
@RequestMapping("/jpa")
public class JPAController {
//内部servlet之间重定向
private final String res = "redirect:/jpa/select";
private final TestDAO testDAO;
// 自动装配的注解
@Autowired
public JPAController(TestDAO testDAO) {
this.testDAO = testDAO;
}
// 删除
@RequestMapping("/delete")
public String delete(TableTest test){
testDAO.delete(test);
return res;
}
// 插入
@RequestMapping("/insert")
public String insert(TableTest test){
testDAO.save(test);
return res;
}
// 分页查询
@RequestMapping("/select")
public String selects(Model model, @RequestParam(value = "start", defaultValue = "0") int start,
@RequestParam(value = "size", defaultValue = "5") int size) throws Exception{
// 记录在数据库中的开始位置; size 表示这一页的长度
start = start <0 ? 0 :start;
// 排序的规则, 按id降序
Sort sort = new Sort(Sort.Direction.DESC, "id");
// 分页的支持
Pageable pageable = new PageRequest(start, size, sort);
Page<TableTest> page;
page = testDAO.findAll(pageable);
// 测试条件查询
System.out.println(testDAO.findByValue("abc").toString());
model.addAttribute("page", page);
return "jpa";
}
// 更新, 含有事务机制
@Transactional
@RequestMapping("/update")
public String update(TableTest test, Model model){
try{
testDAO.save(test);
}catch (Exception e){
// 事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return res;
}
}
这里对使用到的Page和Pageable类做一个说明
public interface Page<T> extends Iterable<T> {
int getNumber(); //当前第几页 返回当前页的数目。总是非负的
int getSize(); //返回当前页面的大小。
int getTotalPages(); //返回分页总数。
int getNumberOfElements(); //返回当前页上的元素数。
long getTotalElements(); //返回元素总数。
boolean hasPreviousPage(); //返回如果有上一页。
boolean isFirstPage(); //返回当前页是否为第一页。
boolean hasNextPage(); //返回如果有下一页。
boolean isLastPage(); //返回当前页是否为最后一页。
Iterator<T> iterator();
List<T> getContent(); //将所有数据返回为List
boolean hasContent(); //返回数据是否有内容。
Sort getSort(); //返回页的排序参数。
}
public interface Pageable {
/**
* 返回要返回的页面.
*
* @return the page to be returned.
*/
int getPageNumber();
/**
* 返回要返回的项目的数量。
*
* @return the number of items of that page
*/
int getPageSize();
/**
* 根据底层页面和页面大小返回偏移量。
*
* @return the offset to be taken
*/
int getOffset();
/**
* 返回排序参数。
*
* @return
*/
Sort getSort();
}