1. JPA和Spring Data简介
    (1)JPA (Java Persistence API)和 Spring Data 是两个范畴的概念。
    (2)作为一名JavaEE工程师,基本都有听说过Hibernate框架。Hibernate是一个ORM框架,而 JPA则是一种ORM规范,JPA和Hibernate的关系就像JDBC与JDBC驱动的关系,即JPA制定了ORM规范,而Hibernate是这些规范的实现(事实上,是先有Hibernate后有JPA, JPA规范的起草者也是Hibernate的作者),因此从功能上来说,JPA相当于Hibernate的一个子集。
    (3)Spring Data是Spring的一个子项目,致力于简化数据库访问,通过规范的方法名称来分析开发者的意图,进而减少数据库访问层的代码量。Spring Data不仅支持关系型数据库,也支持非关系型数据库。Spring Data JPA可以有效简化关系型数据库访问代码。
    Spring Boot 整合 Spring Data JPA 的步骤如下。
  2. 创建数据库
CREATE DATABASE 'jpa' DEFAULT CHARACTER SET utf8;
  1. 创建Spring Boot项目,添加MySQL和Spring Data JPA的依赖
<!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Mybatis-->
        <!--Spring Data JPA-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--druid数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
  1. 数据库配置
# Spring Data JPA
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

第1〜4行是数据库基本信息配置,第5~8行是JPA相关配置。其中,第5行表示是否在控制台打印JPA执行过程生成的SQL,第6行表示JPA对应的数据 库是MySQL,第7行表示在项目启动时根据实体类更新数据库中的表(其他可选值有create、create-drop、validate、no,第8行则表示使用的数据库方言是MySQL57Dialect。

  1. 创建实体
@Entity(name="t_book")
public class Book2 {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private	Integer id;
	@Column(name = "book_name", nullable = false)
 	private	String name;
   	private String author;
   	private Float price;
	@Transient
	private String description;
	//省略 getter/setter

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public Float getPrice() {
		return price;
	}

	public void setPrice(Float price) {
		this.price = price;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Override
	public String toString() {
		return "Book2{" +
				"id=" + id +
				", name='" + name + '\'' +
				", author='" + author + '\'' +
				", price=" + price +
				", description='" + description + '\'' +
				'}';
	}
}

•@Entity注解表示该类是一个实体类,在项目启动时会根据该类自动生成一张表,表的名称 即@Entity注解中name的值,如果不配置name,默认表名为类名。
• 所有的实体类都要有主键,@Id注解表示该属性是一个主键,@GeneratedValue注解表示主 键自动 生成,strategy则表示主键的生成策略。
• 默认情况下,生成的表中字段的名称就是实体类中属性的名称,通过@Column注解可以定制 生成的字段的属性,name表示该属性对应的数据表中字段的名称,nullable表示该字段非空。
• ©Transient注解表示在生成数据库中的表时,该属性被忽略,即不生成对应的字段。

  1. 创建Dao接口
public interface BookDao2 extends JpaRepository<Book2,Integer> {

	List<Book2> getBooksByAuthorStartingWith(String author);

	List<Book2> getBooksByPriceGreaterThan(Float price);

	@Query(value = "select * from t_book where id=(select max(id) from t_book)", nativeQuery = true)
	Book2 getMaxIdBook();

	@Query("select b from t_book b where b.id>:id and b.author=:author")
	List<Book2> getBookByldAndAuthor(@Param("author") String author, @Param("id") Integer id);

	@Query("select b from t_book b where b.id<?2 and b.name like %?1%")
	List<Book2> getBooksByldAndName(String name, Integer id);
}

• 自定义BookDao继承自JpaRepository。JpaRepository中提供了一些基本的数据操作方法,有基本的增删改查、分页查询、排序查询等。

• 第2行定义的方法表示查询以某个字符开始的所有书。

• 第3行定义的方法表示查询单价大于某个值的所有书。

• 在Spring Data JPA中,只要方法的定义符合既定规范,Spring Data就能分析出开发者的意图, 从而避免开发者定义SQL。所谓的既定规范,就是一定的方法命名规则。支持的命名规范如下:

springdata 与 datastax的关系_JPA


springdata 与 datastax的关系_Spring boot_02


• 既定的方法命名规则不一定满足所有的开发需求,因此Spring Data JPA也支持自定义JPQL

(Java Persistence Query Language )或者原生 SQL。第 4~6 行表示查询 id 最大的书,nativeQuery =true表示使用原生的SQL查询.

• 第7〜9行表示根据id和author进行查询,这里使用默认的JPQL语句,JPQL是一种面向对象表达式语言,可以将SQL语法和简单查询语义绑定在一起,使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。JPQL与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性(用过Hibernate的读者会觉得 这类似于HQL)。第7〜9行的查询使用:id,:name这种方式来进行参数绑定。注意:这里使用的列名是属性的名称而不是数据库中列的名称。

• 第10、11行也是自定义JPQL查询,不同的是传参方式使用?1、?2这种方式。注意:方法中 参数的顺序要与参数声明的顺序一致。

如果BookDao中的方法涉及修改操作,就需要@Modifying注解并添加事务。

  1. 创建BookService
@Service
public class BookService3{
		@Autowired
		BookDao2 bookDao;
		public void addBook(Book2 book){
			bookDao.save(book);
		}

		public Page<Book2> getBookByPage(Pageable pageable){
			return bookDao.findAll(pageable);
		}
		public List<Book2> getBooksByAuthorStartingWith(String author){
			return bookDao.getBooksByAuthorStartingWith(author);
		}
		public List<Book2> getBooksByPriceGreaterThan(Float price) {
			return bookDao.getBooksByPriceGreaterThan(price);
		}
		public Book2 getMaxIdBook() {
			return bookDao.getMaxIdBook();
		}
		public List<Book2> getBookByidAndAuthor(String author, Integer id){
			return bookDao.getBookByldAndAuthor(author, id);
		}
		public List<Book2> getBooksByidAndName(String name, Integer id){
			return bookDao.getBooksByldAndName(name, id);
		}
}

• 第6行使用save方法将对象数据保存到数据库,save方法是由JpaRepository接口提供的。
• 第9行是一个分页查询,使用findAll方法,返回值为Page,该对象中包含有分页常用数据,例如总记录数、总页数、每页记录数、当前页记录数等。

  1. 创建BookController
@GetMapping("/findAll")
	public void findAll() {
		PageRequest pageable = PageRequest.of(0, 3);
		Page<Book2> page = bookService3.getBookByPage(pageable);
		System.out.println("总页数:" + page.getTotalPages());
		System.out.println("总记录数:" + page.getTotalElements());
		System.out.println("查询结果:" + page.getContent());
		System.out.println("当前页数:" + (page.getNumber() + 1));
		System.out.println("当前页记录数:" + page.getNumberOfElements());
		System.out.println("每页记录数" + page.getSize());
	}

	@GetMapping("/search")
	public void search() {
		List<Book2> bsl = bookService3.getBookByidAndAuthor("鲁迅", 7);
		List<Book2> bs2 = bookService3.getBooksByAuthorStartingWith("吴");
		List<Book2> bs3 = bookService3.getBooksByidAndName("西", 8);
		List<Book2> bs4 = bookService3.getBooksByPriceGreaterThan(30F);
		Book2 b = bookService3.getMaxIdBook();
		System.out.println("bsl:" + bsl);
		System.out.println("bs2:" + bs2);
		System.out.println("bs3:" + bs3);
		System.out.println("bs4:" + bs4);
		System.out.println(" b :" + b);
	}
	@GetMapping("/save")
	public void save(){
		Book2 book = new Book2();
		book.setAuthor("鲁迅");
		book.setName("呐喊");
		book.setPrice(23F);
		bookService3.addBook(book);
	}

• 在findAll接口中,首先通过调用PageRequest中的of方法构造PageRequest对象。of方法接收两个参数:第一个参数是页数,从0开始计;第二个参数是每页显示的条数。
• 在save接口中构造一个Book对象,直接调用save方法保存起来即可。

  1. 启动服务器测试 如图所示:
    网不太好 ! 等网络好了 在截图补上!!! 么么哒