SpringBoot整合SpringDataJPA十

一、Spring Data JPA介绍

spring data:spring data其实就是spring提供的一个操作数据的框架,而spring date jpa是spring data框架下一个基于JPA标准操作的模块。

spring date jpa:基于JPA标准对数据对操作,简化持久层对代码,开发人员只需要编写接口即可。

二、Spring Boot整合Spring Data JPA

1 创建项目

这里略

2 添加坐标

<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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
	</parent>
	<groupId>com.bjsxt</groupId>
	<artifactId>22-spring-boot-jpa</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<java.version>1.7</java.version>
		<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
	</properties>

	<dependencies>
		<!-- springBoot的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springBoot的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<!-- springBoot的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		
		<!-- 测试工具的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>

		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!-- druid连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.9</version>
		</dependency>

	</dependencies>
</project>

3.添加application.properties配置文件

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=root

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

4 添加实体类

@Table(name=“t_users”) 1.表示和数据库对表做映射 2.如果用正向工程,name对值表示数据库表对名字

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_users")
public class Users {

	@Id//主键
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键对生成策略
	@Column(name="id")//完成一个对象id属性和表对字段映射关系,还有一层含有就是正向工厂生成表时对对应关系
	private Integer id;
	
	@Column(name="name")
	private String name;
	
	@Column(name="age")
	private Integer age;
	
	@Column(name="address")
	private String address;
	
	@ManyToOne(cascade=CascadeType.PERSIST)
	//@JoinColumn:维护外键
	@JoinColumn(name="roles_id")
	private Roles roles;

	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 Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "Users [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
	}

	public Roles getRoles() {
		return roles;
	}

	public void setRoles(Roles roles) {
		this.roles = roles;
	}
	
	
}

5 编写一个dao接口

JpaRepository<T,ID> T :当前需要映射的实体 ID :当前映射的实体中的主键的类型

import org.springframework.data.jpa.repository.JpaRepository;
import com.bjsxt.pojo.Users;
/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository<Users,Integer>{

}

6 测试,这里不懂可以看往期对Spring Data JPA讲解

测试工具的启动器依赖:

<!-- 测试工具的启动器 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
</dependency>

@RunWith(SpringJUnit4ClassRunner.class): 用RunWith启动器启动spring和JUnit对整合 SpringJUnit4ClassRunner.class:做整合类 @SpringBootTest(classes = App.class):告诉这个测试类,启动项目对启动类在什么地方

这里因为我们开启类一个正向工程对配置spring.jpa.hibernate.ddl-auto=update,我们数据没有这张表也会创建。

/**
 * 测试类
 *
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = App.class)
public class UsersRepositoryTest {

	@Autowired
	private UsersRepository usersRepository;

	@Test
	public void testSave() {
		Users users = new Users();
		users.setAddress("上海市");
		users.setAge(24);
		users.setName("王五");
		this.usersRepository.save(users);
	}
}

7 启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class App {

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

三、Spring Data JPA核心接口(复习)

1.Repository 接口 2.CrudRepository 接口 3.PagingAndSortingRepository 接口 4.JpaRepository 接口 5.JpaSpecificationExecutor 接口

四、Repository接口

1 提供方法名称类命名方式查询

1)dao接口对编写:

import java.util.List;
import org.springframework.data.repository.Repository;
import com.bjsxt.pojo.Users;

/**
 * Repository接口的方法名称命名查询
 *
 *
 */
public interface UsersRepositoryByName extends Repository<Users, Integer> {

	//方法的名称必须要遵循驼峰式命名规则。findBy(关键字)+属性名称(首字母要大写)+查询条件(首字母大写)
	List<Users> findByName(String name);
	
	List<Users> findByNameAndAge(String name,Integer age);
	
	List<Users> findByNameLike(String name);
}

2)测试类

	@Autowired
	private UsersRepositoryByName usersRepositoryByName;

	/**
	 * Repository--方法名称命名测试
	 */
	@Test
	public void testFindByName() {
		List<Users> list = this.usersRepositoryByName.findByName("张三");
		for (Users users : list) {
			System.out.println(users);
		}
	}

	/**
	 * Repository--方法名称命名测试
	 */
	@Test
	public void testFindByNameAndAge() {
		List<Users> list = this.usersRepositoryByName.findByNameAndAge("张三", 20);
		for (Users users : list) {
			System.out.println(users);
		}
	}

	/**
	 * Repository--方法名称命名测试
	 */
	@Test
	public void testFindByNameLike() {
		List<Users> list = this.usersRepositoryByName.findByNameLike("张%");
		for (Users users : list) {
			System.out.println(users);
		}
	}

这里确定其实很明显,如果查询条件很多,这里方法名就会很长。

2 注解@Query查询方式

1)dao接口编写

import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import com.bjsxt.pojo.Users;

/**
 * Repository   @Query
 *
 *
 */
public interface UsersRepositoryQueryAnnotation extends Repository<Users, Integer> {

	@Query("from Users where name = ?")
	List<Users> queryByNameUseHQL(String name);
	
	@Query(value="select * from t_users where name = ?",nativeQuery=true)
	List<Users> queryByNameUseSQL(String name);
	
	@Query("update Users set name  = ? where id  = ?")
	@Modifying //需要执行一个更新操作
	void updateUsersNameById(String name,Integer id);
}

2)测试类

	@Autowired
	private UsersRepositoryQueryAnnotation usersRepositoryQueryAnnotation;

	/**
	 * Repository--@Query测试
	 */
	@Test
	public void testQueryByNameUseHQL() {
		List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseHQL("张三");
		for (Users users : list) {
			System.out.println(users);
		}
	}

	/**
	 * Repository--@Query测试
	 */
	@Test
	public void testQueryByNameUseSQL() {
		List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseSQL("张三");
		for (Users users : list) {
			System.out.println(users);
		}
	}

	/**
	 * Repository--@Query测试
	 */
	@Test
	@Transactional //@Transactional与@Test 一起使用时 事务是自动回滚的。
	@Rollback(false) //取消自动回滚
	public void testUpdateUsersNameById() {
		this.usersRepositoryQueryAnnotation.updateUsersNameById("张三三", 1);
	}

五、CrudRepository 接口

作用:完成增删改查到操作,它是继承类Repository接口 事物它已经开启类 在这里插入图片描述

1 dao接口编写

import org.springframework.data.repository.CrudRepository;
import com.bjsxt.pojo.Users;

/**
 * CrudRepository接口
 *
 *
 */
public interface UsersRepositoryCrudRepository extends CrudRepository<Users, Integer> {
}

2 测试类编写

	@Autowired
	private UsersRepositoryCrudRepository usersRepositoryCrudRepository;

	/**
	 * CrudRepository测试
	 */
	@Test
	public void testCrudRepositorySave() {
		Users user = new Users();
		user.setAddress("天津");
		user.setAge(32);
		user.setName("张三丰");
		this.usersRepositoryCrudRepository.save(user);
	}
	
	/**
	 * CrudRepository测试
	 */
	@Test
	public void testCrudRepositoryUpdate() {
		Users user = new Users();
		user.setId(4);
		user.setAddress("南京");
		user.setAge(40);
		user.setName("张三丰");
		this.usersRepositoryCrudRepository.save(user);
	}
	
	/**
	 * CrudRepository测试
	 */
	@Test
	public void testCrudRepositoryFindOne() {
		Users users = this.usersRepositoryCrudRepository.findOne(4);
		System.out.println(users);
	}
	
	/**
	 * CrudRepository测试
	 */
	@Test
	public void testCrudRepositoryFindAll() {
		List<Users> list  =  (List<Users>)this.usersRepositoryCrudRepository.findAll();
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	/**
	 * CrudRepository测试
	 */
	@Test
	public void testCrudRepositoryDeleteById() {
		this.usersRepositoryCrudRepository.delete(4);
		
	}
	

六、PagingAndSortingRepository 接口

特点:从名称可以看出,提供分页和排序到接口 继承:CrudRepository接口 在这里插入图片描述

1)dao接口编写

import org.springframework.data.repository.PagingAndSortingRepository;
import com.bjsxt.pojo.Users;
/**
 * 
 *PagingAndSortingRepository接口
 *
 */
public interface UsersRepositoryPagingAndSorting extends PagingAndSortingRepository<Users,Integer> {

}

2)编写测试类

	@Autowired
	private UsersRepositoryPagingAndSorting usersRepositoryPagingAndSorting;
		
	/**
	 * PagingAndSortingRepository   排序测试
	 */
	@Test
	public void testPagingAndSortingRepositorySort() {
		//Order 定义排序规则
		Order order = new Order(Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort = new Sort(order);
		List<Users> list = (List<Users>)this.usersRepositoryPagingAndSorting.findAll(sort);
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	/**
	 * PagingAndSortingRepository   分页测试
	 */
	@Test
	public void testPagingAndSortingRepositoryPaging() {
		//Pageable:封装了分页的参数,当前页,每页显示的条数。注意:他的当前页是从0开始。
		//PageRequest(page,size) page:当前页。size:每页显示的条数
		Pageable pageable = new PageRequest(1, 2);
	    Page<Users> page = this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("总条数:"+page.getTotalElements());
		System.out.println("总页数"+page.getTotalPages());
		List<Users> list = page.getContent();
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	/**
	 * PagingAndSortingRepository   排序+分页
	 */
	@Test
	public void testPagingAndSortingRepositorySortAndPaging() {
		
		Sort sort = new Sort(new Order(Direction.DESC, "id"));
		
		Pageable pageable = new PageRequest(1, 2, sort);
				
		Page<Users> page = this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("总条数:"+page.getTotalElements());
		System.out.println("总页数"+page.getTotalPages());
		List<Users> list = page.getContent();
		for (Users users : list) {
			System.out.println(users);
		}
	}

七、JpaRepository 接口

继承:PagingAndSortingRepository接口 这个接口是我们在开发过程中最常用到接口,接口提供其他父接口方法返回值适配。 在这里插入图片描述 在这里插入图片描述 对比就很明显类

1)编写dao接口

import org.springframework.data.jpa.repository.JpaRepository;

import com.bjsxt.pojo.Users;
/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository<Users,Integer>{

}

2)测试代码

	@Autowired
	private UsersRepository usersRepository;
	
	/**
	 * JapRepository   排序测试
	 */
	@Test
	public void testJpaRepositorySort() {
		//Order 定义排序规则
		Order order = new Order(Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort = new Sort(order);
		List<Users> list = this.usersRepository.findAll(sort);
		for (Users users : list) {
			System.out.println(users);
		}
	}

八、JpaSpecificationExecutor 接口

特点:提供多条件和复杂查询的处理,而且在查询中添加分页与排序 继承:没有继承任何接口,要依赖JpaRepository一起使用 在这里插入图片描述 在这里插入图片描述

1)dao接口编写

mport org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import com.bjsxt.pojo.Users;
/**
 * 
 *JpaSpecificationExecutor
 *
 */
public interface UsersRepositorySpecification extends JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users> {

}

2)测试类编写

	@Autowired
	private UsersRepositorySpecification usersRepositorySpecification;

	/**
	 * JpaSpecificationExecutor   单条件测试
	 */
	@Test
	public void testJpaSpecificationExecutor1() {
		
		/**
		 * Specification<Users>:用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			
			//Predicate:封装了 单个的查询条件
			/**
			 * Root<Users> root:查询对象的属性的封装。
			 * CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分的信息,select  from order by
			 * CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// where name = '张三三'
				/**
				 * 参数一:查询的条件属性
				 * 参数二:条件的值
				 */
				Predicate pre = cb.equal(root.get("name"), "张三三");
				return pre;
			}
		};
		List<Users> list = this.usersRepositorySpecification.findAll(spec);
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	
	/**
	 * JpaSpecificationExecutor   多条件测试
	 */
	@Test
	public void testJpaSpecificationExecutor2() {
		
		/**
		 * Specification<Users>:用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			
			//Predicate:封装了 单个的查询条件
			/**
			 * Root<Users> root:查询对象的属性的封装。
			 * CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分的信息,select  from order by
			 * CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// where name = '张三三' and age = 20
				List<Predicate> list = new ArrayList<>();
				list.add(cb.equal(root.get("name"),"张三三"));
				list.add(cb.equal(root.get("age"),20));
				Predicate[] arr = new Predicate[list.size()];
				return cb.and(list.toArray(arr));
			}
		};
		List<Users> list = this.usersRepositorySpecification.findAll(spec);
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	/**
	 * JpaSpecificationExecutor   多条件测试第二种写法
	 */
	@Test
	public void testJpaSpecificationExecutor3() {
		
		/**
		 * Specification<Users>:用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			
			//Predicate:封装了 单个的查询条件
			/**
			 * Root<Users> root:查询对象的属性的封装。
			 * CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分的信息,select  from order by
			 * CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// where name = '张三三' and age = 20
				/*List<Predicate> list = new ArrayList<>();
				list.add(cb.equal(root.get("name"),"张三三"));
				list.add(cb.equal(root.get("age"),20));
				Predicate[] arr = new Predicate[list.size()];*/
				//(name = '张三' and age = 20) or id = 2
				return cb.or(cb.and(cb.equal(root.get("name"),"张三三"),cb.equal(root.get("age"),20)),cb.equal(root.get("id"), 2));
			}
		};
		
		Sort sort = new Sort(new Order(Direction.DESC,"id"));
		List<Users> list = this.usersRepositorySpecification.findAll(spec,sort);
		for (Users users : list) {
			System.out.println(users);
		}
	}
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4512.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!