zoukankan      html  css  js  c++  java
  • spring data jpa

    spring data jpa介绍

    可以看出 spring data jpa 其实是一种抽象,spring将不同的 jpa 实现归纳成一种规范;

    所以,如果使用 spring data jpa 的话,就不用考虑其 jpa 实现是如何使用的了,只需要掌握 spring data jpa 使用即可;

    快速入门案例

    pom.xml

    <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.td</groupId>
    	<artifactId>spring-data-jpa</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	
    	<!-- 依赖 -->
    	<dependencies>
    		<!-- spring base -->	
    		<dependency>
    		    <groupId>org.springframework</groupId>
    		    <artifactId>spring-orm</artifactId>
    		    <version>5.0.8.RELEASE</version>
    		</dependency>
    		
    		<!-- hibernate -->
    		<dependency>
    		    <groupId>org.hibernate</groupId>
    		    <artifactId>hibernate-core</artifactId>
    		    <version>5.3.6.Final</version>
    		</dependency>
    		
    		<!-- c3p0 -->
    		<dependency>
    		    <groupId>com.mchange</groupId>
    		    <artifactId>c3p0</artifactId>
    		    <version>0.9.5.2</version>
    		</dependency>
    		
    		<!-- spring data jpa -->
    		<dependency>
    		    <groupId>org.springframework.data</groupId>
    		    <artifactId>spring-data-jpa</artifactId>
    		    <version>2.1.0.RELEASE</version>
    		</dependency>
    		
    		<!-- mysql -->
    		<dependency>
    		    <groupId>mysql</groupId>
    		    <artifactId>mysql-connector-java</artifactId>
    		    <version>8.0.12</version>
    		</dependency>
    		
    		<!-- junit -->
    		<dependency>
    		    <groupId>junit</groupId>
    		    <artifactId>junit</artifactId>
    		    <version>4.12</version>
    		    <scope>test</scope>
    		</dependency>
    	
    	</dependencies>
    </project>
    

    Person实体

    package com.td.entity;
    
    import java.util.Date;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.GenericGenerator;
    
    @Entity
    @Table(name = "person")
    public class Person {
    
    	private Integer id;
    	private String name;
    	private Date birthday;
    
    	public Person() {
    	}
    
    	public Person(Integer id, String name, Date birthday) {
    		this.id = id;
    		this.name = name;
    		this.birthday = birthday;
    	}
    
    	public Date getBirthday() {
    		return birthday;
    	}
    
    	@Id
    	@GeneratedValue(generator="_native")
    	@GenericGenerator(strategy="native", name="_native")
    	public Integer getId() {
    		return id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setBirthday(Date birthday) {
    		this.birthday = birthday;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	@Override
    	public String toString() {
    		return "Person [id=" + id + ", name=" + name + ", birthday=" + birthday + "]";
    	}
    
    }
    

    Repository接口(重点关注对象)

    package com.td.repository;
    
    import org.springframework.data.repository.Repository;
    
    import com.td.entity.Person;
    
    // spring 会使用代理来产生该接口的bean并添加到ioc容器中
    public interface PersonRepository extends Repository<Person, Integer> {
    
    	// 根据名称查找person
        // 【方法名称参考 Repository查询方法命名规范】
    	Person getByName(String name);
    }
    
    

    使用测试

    package com.td.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.td.entity.Person;
    import com.td.repository.PersonRepository;
    
    public class RepositoryTest {
    
    	private ApplicationContext ac = null;
    	
    	{
    		ac = new ClassPathXmlApplicationContext("spring.xml");
    	}
    
    	// 根据name查询
    	@Test
    	public void test2() {
    		PersonRepository personRepo = ac.getBean(PersonRepository.class);
    		Person byName = personRepo.getByName("谭迪");
    		System.out.println(byName);
    	}
    
    }
    
    

    Repository接口介绍

    基本接口有一下几种

    接口介绍

    Repository:基本接口(标记接口),可根据 spring data jpa 命名规范创建相应的 crud 接口方法

    CrudRepository:提供基本的crud操作

    PagingAndSortingRepository:继承CrudRepository,并提供分页和排序操作

    JpaRepository:继承PagingAndSortingRepository,并提供一些 findAll(xx)和 批量删除等操作

    JpaSpecificationExecutor:提供多条件分页查询操作

    spring提供的repository实现

    SimpleJpaRepository.java

    @Repository
    @Transactional(readOnly = true)
    public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
        // ...
    }
    

    该类是 spring 提供的实现,提供了很多常用的操作;该类的性质类似于 JdbcTtemplate/HibernateTemplate

    Repository查询方法命名规则

    图片源自网络

    @Query注解使用(常用)

    基本说明

    使用该注解可以手动设置SQL语句;使用了@Query的方法可以不遵循 Repository查询方法命名规范 也能正常运行,并且支持 通配符 和 命名参数 来指定条件

    使用案例

    Repository接口

    package com.td.repository;
    
    import java.util.List;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.data.repository.query.Param;
    
    import com.td.entity.Person;
    
    public interface PersonRepository extends JpaRepository<Person, Integer>, JpaSpecificationExecutor<Person>{
    
    	// 根据名称查找person
    	Person getByName(String name);
    	
    	
    	/**
    	 *	查询id最大的person
    	 * 	@return
    	 */
    	@Query("FROM Person p1 WHERE p1.id=(SELECT max(p2.id) FROM Person p2)")
    	Person getMaxIdPerson();
    	
    	/**
    	 *	查询id最大的person - 使用原生SQL查询
    	 *	nativeQuery=true 启动 原生SQL查询
    	 * 	@return
    	 */
    	@Query(nativeQuery=true, value="SELECT * FROM person p1 WHERE p1.id=(SELECT max(p2.id) FROM person p2)")
    	Person getMaxIdPerson2();
    
    	/**
    	 *	查询指定名称和id的记录 - 占位符方式
    	 */
    	@Query("FROM Person p WHERE p.name = ?1 AND p.id = ?2")
    	List<Person> testByNameAndId1(String name, int id);
    	
    	/**
    	 *	查询指定名称和id的记录 - 命名参数方式
    	 */
    	@Query("SELECT p FROM Person p WHERE p.name = :name AND p.id = :id")
    	List<Person> testByNameAndId2(@Param("name") String name, @Param("id") int id);
    	
    }
    

    使用测试

    // 测试 - @Query基本使用
    @Test
    public void test1() {
        PersonRepository personRepo = ac.getBean(PersonRepository.class);
        Person maxIdPerson = personRepo.getMaxIdPerson();
        System.out.println(maxIdPerson);
    }
    
    // 测试 - 占位符绑定
    @Test
    public void test4() {
        System.out.println("RepositoryTest.test4()");
        PersonRepository personRepo = ac.getBean(PersonRepository.class);
        List<Person> person = personRepo.testByNameAndId1("谭迪", 1);
        System.out.println(person);
    }
    
    // 测试 - 名称参数绑定
    @Test
    public void test5() {
        System.out.println("RepositoryTest.test5()");
        PersonRepository personRepo = ac.getBean(PersonRepository.class);
        List<Person> person = personRepo.testByNameAndId1("谭迪", 1);
        System.out.println(person);
    }
    
    // 测试 - 原生SQL查询
    @Test
    public void test6() {
        PersonRepository personRepo = ac.getBean(PersonRepository.class);
        Person maxIdPerson = personRepo.getMaxIdPerson2();
        System.out.println(maxIdPerson);
    }
    

    @Modifying注解使用(常用)

    基本说明

    该注解用于修饰修改操作,一般配置@Query使用

    使用案例

    Repository接口

    public interface PersonRepository extends Repository<Person, Integer>, JpaSpecificationExecutor<Person>{
    	
    	
    	/**
    	 * 	根据id更新person名称
    	 * 	更新操作不用@Modifying时:QueryExecutionRequestException: Not supported for DML operations
    	 */
    	@Modifying
    	@Query("UPDATE Person SET name=?1 WHERE id=?2")
    	void updateNameById(String name, int id);
    }
    

    Service接口

    @Service
    public class PersonService {
    
        @Autowired
        private PersonRepository personRepository;
    
        @Transactional
        public void updateNameById(String name, int id) {
            personRepository.updateNameById(name, id);
        }
    }
    

    使用测试

    public class RepositoryTest {
    
    	private ApplicationContext ac = null;
    	
    	{
    		ac = new ClassPathXmlApplicationContext("spring.xml");
    	}
    	
    	// 根据name查询
    	@Test
    	public void test0() {
    		PersonService service = ac.getBean(PersonService.class);
    		service.updateNameById("超人", 1); //修改
    	}
    }
    

    Repository接口使用

    基本说明

    以下案例使用 org.springframework.data.jpa.repository.JpaRepository<T, ID> 做说明,接口如下:

    // 表示该接口不是一个RepositoryBean,即ioc容器不会为其产生代理对象
    @NoRepositoryBean
    public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    

    接口方法如下:

    https://docs.spring.io/spring-data/jpa/docs/2.1.0.RELEASE/api/

    使用案例 - 分页和JpaSpecificationExecutor接口使用

    Repository接口

    public interface PersonRepository extends JpaRepository<Person, Integer>, JpaSpecificationExecutor<Person>{ }
    

    测试使用

    @Test
    public void test() {
    
        PersonRepository personRepo = ac.getBean(PersonRepository.class);
    
        Specification<Person> specification = new Specification<Person>() {
    
            /**
    			 * Root:用户获取实体类中的信息(作为查询条件)
    			 * CriteriaQuery:
    			 * CriteriaBuilder:构建查询条件Predicate
    			 */
            public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 获取Path方法1
                Path path = root.get("id"); // 获取字段id作为where条件
                Predicate gt = criteriaBuilder.gt(path, 4); //gt表示大于,即id大于4的数据
                return gt;
            }
        };
    
        // 参数1:当前页(从0开始)
        // 参数2:每页显示的记录数
        PageRequest pageable = PageRequest.of(0, 2);
        Page<Person> page = personRepo.findAll(specification, pageable); //分页查询
    
        System.out.println("总记录数: " + page.getTotalElements());
        System.out.println("当前第几页: " + (page.getNumber() + 1));
        System.out.println("总页数: " + page.getTotalPages());
        System.out.println("当前页面的 List: " + page.getContent());
        System.out.println("当前页面的记录数: " + page.getNumberOfElements());
    }
    
  • 相关阅读:
    List of the best open source software applications
    Owin对Asp.net Web的扩展
    NSwag给api加上说明
    'workspace' in VS Code
    unable to find valid certification path to requested target
    JMeter的下载以及安装使用
    exception disappear when forgot to await an async method
    Filter execute order in asp.net web api
    记录web api的request以及response(即写log)
    asp.net web api的源码
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9706906.html
Copyright © 2011-2022 走看看