SpringBoot整合Spring Data JPA

1、SpringBoot Data JPA介绍

        Spring Data:其实SpringData就是Spring提供了一个操作数据的框架。而SpringData JPA只是SpringData框架下的一个基于JPA标准操作数据的模块。
        Spring Data JPA:基于JPA的标准数据进行操作。简化操作持久层的代码。只需要编写接口就可以。

        具体可见spring官方网站。

2、SpringBoot整合Spring Data JPA

1)在pom中添加依赖



   org.springframework.boot
   spring-boot-starter-data-jpa

2)修改application.properties / application.yml文件中添加配置

 

server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:9006/sm_db?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456

  jpa:
    hibernate:
      #  jpa的正向工程
      ddl-auto: update
    # 显示sql
    show-sql: true

说明:

spring.jpa.hibernate.ddl-auto=update            jpa的正向工程

srpng.jpa.show-sql=true        显示sql

3)添加实体类

/**
  * @Data:让其类下的所有属性都有getset方法
  * @ToString:生成一个tostring的方法
  * 这两个lombok下的工具类
  * 使用lombok需要在idea安装插件,在File -> Settings 菜单 , 或Ctrl + Alt + S 快捷键,
  * 打开设置面板 . 并切换到Plugins插件视图,在搜索框输入lombok进行搜索。
  * 使用需要在pom里面添加依赖
  * 
  *    org.projectlombok
  *    lombok
  *    true
  * 
  */
@Data
@ToString

// @Entity 定义这个类是实体类
@Entity
// @Table 数据库中对应的表,name 对应的表名
@Table(name = "t_user")
public class User {

  // @Id 标志这个属性是个id
  @Id
  // @GeneratedValue 标志是个自增主键
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  // @Column 数据库中对应的字段
  @Column(name = "lid")
  private Long lid;

  @Column(name = "username")
  private String username;

  @Column(name = "mobilephone")
  private String mobilephone;

  @Column(name = "email")
  private String email;
}

4)编写Dao接口

/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 */
public interface UserRepository extends JpaRepository {

}

5)在pom文件中添加测试启动器的坐标


   org.springframework.boot
   spring-boot-starter-test
   test

6)测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ProjectFrame2Application.class })
class ProjectFrame2ApplicationTests {

    @Autowired
    private UserService userService;

    @Test
    public void testSave() {
        User user = new User();
        user.setUsername("测试");
        user.setMobilephone("12345678910");
        user.setEmail("[email protected]");
        this.userRepository.save(user);
    }
}

3、SpringBoot JPA提供的核心接口

        1、Repository接口
        2、CrudRepository接口
        3、PagingAndSortingRepository接口
        4、JpaRepository接口
        5、JPASpecificationExecutor接口

1)Repository接口的使用

    提供了方法名称命名查询方式
    提供了基于@Query注解查询与更新

1、dao层接口(方法名称命名查询方式)

/**
 * Repository接口方法名称命名查询
 *
 */
public interface UsersRepositoryByName extends Repository {
    //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写)
    // 根据name和年龄进行查询
    List findByName(String name);

    // 根据name和age进行查询
    List findByNameAndAge(String name,Integer age);

    // findByNameLike 根据name条件进行模糊查询
    List findByNameLike(String name);

}

2、dao层接口编写(基于@Query注解查询与更新)


/**
 * 〈一句话功能简述〉
* Repository @Query * * @author admin * @create 2019/5/22 * @since 1.0.0 */ public interface UsersRepositoryQueryAnnotation extends JpaRepository { @Query("from Users where name = ?") List queryByNameUseHQL(String name); @Query(value = "select * from t_user where name=?",nativeQuery = true) List queryByNameUseSQL(String name); @Query("update Users set name=? where id=?") @Modifying //需要执行一个更新操作 void updateUserNameById(String name,Long id); }

2)、CrudRepository接口的使用

      CrudRepository接口,主要是完成一些增删改查的操作。注意:CrudRepository接口继承了Repository接口

1、编写dao层接口

public interface UsersRepositoryCrudRepository extends CrudRepository {
}

2、测试

    @Test
	public void testCrudRepositorySave() {
		User user = new User();
        user.setUsername("测试1");
        user.setMobilephone("12345678911");
        user.setEmail("[email protected]");
		this.userRepositoryCrudRepository.save(users);
	}

	@Test
	public void testCrudRepositoryUpdate() {
		User user = new User();
        user.setLid(1L);
        user.setUsername("测试2");
        user.setMobilephone("12345678912");
        user.setEmail("[email protected]");
		this.userRepositoryCrudRepository.save(users);
	}

	@Test
	public void testCrudRepositoryFindOne() {
		User user=this.userRepositoryCrudRepository.findOne(4);
		System.out.println(user);
	}

	@Test
	public void testCrudRepositoryFindAll() {
		List list= (List) this.userRepositoryCrudRepository.findAll();
		for (User user : list){
			System.out.println(user);
		}
	}

	@Test
	public void testCrudRepositoryDeleteById() {
		this.usersRepositoryCrudRepository.delete(2);
		
	}

3)PagingAndSortingRepository接口的使用

该接口提供了分页与排序的操作,注意:该接口继承了CrudRepository接口

1、编写dao层

public interface UsersRepositoryPagingAndSorting extends PagingAndSortingRepository {

}

2、测试

    @Test
	public void testPagingAndSortingRepositorySort() {
		//Order	定义了排序规则
		Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort=new Sort(order);
		List list = (List) this.usersRepositoryPagingAndSorting.findAll(sort);
		for (User user:list){
			System.out.println(user);
		}
	}

	@Test
	public void testPagingAndSortingRepositoryPaging() {
		//Pageable:封装了分页的参数,当前页,煤业显示的条数。注意:它的当前页是从0开始
		//PageRequest(page, size):page表示当前页,size表示每页显示多少条
		Pageable pageable=new PageRequest(1,2);
		Page page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List list = page.getContent();
		for (User user : list){
			System.out.println(user);
		}
	}

	@Test
	public void testPagingAndSortingRepositorySortAndPaging() {
		Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"id"));
		Pageable pageable=new PageRequest(0, 2, sort);
		Page page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List list=page.getContent();
		for (User user : list){
			System.out.println(user);
		}
	}

4)JpaRepository接口

该接口继承了PagingAndSortingRepository。对继承的父接口中方法的返回值进行适配。

1、dao层接口编写

/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository {

}

2、测试

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

5)JPASpecificationExecutor接口

该接口主要是提供了多条件查询的支持,并且可以在查询中添加排序与分页。注意JPASpecificationExecutor是单独存在的。完全独立

1、dao层接口编写

public interface UserRepositorySpecification extends JpaRepository,JpaSpecificationExecutor {
}

2、测试

    /**
	 * JpaSpecificationExecutor		单条件查询
	 */
	@Test
	public void testJpaSpecificationExecutor1() {
		/**
		 * Specification:用于封装查查询条件
		 */
		Specification spec=new Specification() {
			//Predicate:封装了单个查询条件

			/**
			 * @param root		对查询对象属性的封装
			 * @param criteriaQuery	封装了我们要执行的查询中的各个部分的信息,select from order
			 * @param criteriaBuilder	查询条件的构造器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
				//where name="张三"
				/**
				 * 参数一:查询的属性
				 * 参数二:条件的值
				 */
				Predicate predicate=criteriaBuilder.equal(root.get("username"),"张三");
				return predicate;
			}
		};
		List list=this.userRepositorySpecification.findAll(spec);
		for (Users user:list){
			System.out.println(user);
		}
	}

	/**
	 * JpaSpecificationExecutor		多条件查询方式一
	 */
	@Test
	public void testJpaSpecificationExecutor2() {
		/**
		 * Specification:用于封装查查询条件
		 */
		Specification spec=new Specification() {
			//Predicate:封装了单个查询条件

			/**
			 * @param root		对查询对象属性的封装
			 * @param criteriaQuery	封装了我们要执行的查询中的各个部分的信息,select from order
			 * @param criteriaBuilder	查询条件的构造器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
				//where name="张三" and age=20
				/**
				 * 参数一:查询的属性
				 * 参数二:条件的值
				 */
				List list=new ArrayList<>();
				list.add(criteriaBuilder.equal(root.get("username"),"张三"));
				list.add(criteriaBuilder.equal(root.get("mail"),"[email protected]"));
				Predicate[] arr=new Predicate[list.size()];
				return criteriaBuilder.and(list.toArray(arr));
			}
		};
		List list=this.userRepositorySpecification.findAll(spec);
		for (User user:list){
			System.out.println(user);
		}
	}

	/**
	 * JpaSpecificationExecutor		多条件查询方式二
	 */
	@Test
	public void testJpaSpecificationExecutor3() {
		/**
		 * Specification:用于封装查查询条件
		 */
		Specification spec=new Specification() {
			//Predicate:封装了单个查询条件

			/**
			 * @param root		对查询对象属性的封装
			 * @param criteriaQuery	封装了我们要执行的查询中的各个部分的信息,select from order
			 * @param criteriaBuilder	查询条件的构造器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
				//where username="张三" and mail="[email protected]"
				/**
				 * 参数一:查询的属性
				 * 参数二:条件的值
				 */
				/*List list=new ArrayList<>();
				list.add(criteriaBuilder.equal(root.get("username"),"张三"));
				list.add(criteriaBuilder.equal(root.get("mail"), "[email protected]"));
				Predicate[] arr=new Predicate[list.size()];*/
				//(username='张三' and mail="[email protected]") or lid=2L
				return criteriaBuilder.or(criteriaBuilder.and(criteriaBuilder.equal(root.get("username"),"张三"),criteriaBuilder.equal(root.get("mail"),"[email protected]")),criteriaBuilder.equal(root.get("lid"),2L));
			}
		};

		Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"lid"));
		List list=this.userRepositorySpecification.findAll(spec,sort);
		for (User user:list){
			System.out.println(user);
		}
	}

4、关联映射操作

1、一对多的关联关系
  需求:角色与用户的一对多的关联关系
  角色:一方
  用户:多方

1)实体类

/**
 * 
 */
@Data
@Entity
@Table(name = "t_roles")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Integer roleId;

    @Column(name = "role_name")
    private String roleName;

    @OneToMany(mappedBy = "roles")
    private Set user=new HashSet<>();

}
@Data
@ToString(exclude = {"roles"})
@Entity
@Table(name="t_users")
public class Users {

	@Id	//主键id
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
	@Column(name="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(name ="role_id")	//维护一个外键,外键在Users一侧
	private Roles roles;

}

2)dao层接口编写

/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository {

}

3)测试

/**
 * 〈一句话功能简述〉
* 多对多的关联关系的测试 * * @author admin * @create 2019/5/23 * @since 1.0.0 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = {ProjectFrame2Application.class}) public class ManyToManyTest { @Autowired private RolesRepository rolesRepository; /** * 添加测试 */ @Test public void testSave(){ //创建角色对象 Roles roles=new Roles(); roles.setRoleName("项目经理"); //创建菜单对象 Menus menus=new Menus(); menus.setMenusName("xxxx管理系统"); menus.setFatherId(0); Menus menus2=new Menus(); menus2.setFatherId(1); menus2.setMenusName("项目管理"); //关联 roles.getMenus().add(menus); roles.getMenus().add(menus2); menus.getRoles().add(roles); menus2.getRoles().add(roles); //保存 this.rolesRepository.save(roles); } /** * 查询操作 */ @Test public void testFind(){ Roles roles=this.rolesRepository.findOne(2); System.out.println(roles.getRoleName()); Set menus=roles.getMenus(); for (Menus menu:menus){ System.out.println(menu); } } }

2、多对多的关联关系
 角色与菜单多对多关联关系
 菜单:多方
 角色:多方

1)实体类

@Data
@ToString(exclude = {"roles"})
@Entity
@Table(name = "t_menus")
public class Menus {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "menus_id")
    private Integer menusId;

    @Column(name = "menus_name")
    private String menusName;

    @Column(name = "menus_url")
    private String menusUrl;

    @Column(name = "father_id")
    private Integer fatherId;

    @ManyToMany(mappedBy = "menus")
    private Set roles=new HashSet<>();
}
@Data
@Entity
@Table(name = "t_roles")
public class Roles {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Integer roleId;

    @Column(name = "role_name")
    private String roleName;

    @OneToMany(mappedBy = "roles")
    private Set users=new HashSet<>();

    @ManyToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
    //映射中间表  joinColumns:当前表中的主键关联中间表的外键
    @JoinTable(name = "t_roles_menus",joinColumns =@JoinColumn(name = "role_id"),inverseJoinColumns = @JoinColumn(name = "menu_id"))
    private Set menus=new HashSet<>();

2)dao层接口

public interface RolesRepository extends JpaRepository {
}

3)测试

/**
 * 多对多的关联关系的测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ProjectFrame2Application.class})
public class ManyToManyTest {

    @Autowired
    private RolesRepository rolesRepository;

    /**
     * 添加测试
     */
    @Test
    public void testSave(){
        //创建角色对象
        Roles roles=new Roles();
        roles.setRoleName("项目经理");
        //创建菜单对象
        Menus menus=new Menus();
        menus.setMenusName("xxxx管理系统");
        menus.setFatherId(0);

        Menus menus2=new Menus();
        menus2.setFatherId(1);
        menus2.setMenusName("项目管理");
        //关联
        roles.getMenus().add(menus);
        roles.getMenus().add(menus2);
        menus.getRoles().add(roles);
        menus2.getRoles().add(roles);
        //保存
        this.rolesRepository.save(roles);
    }

    /**
     * 查询操作
     */
    @Test
    public void testFind(){
        Roles roles=this.rolesRepository.findOne(2);
        System.out.println(roles.getRoleName());
        Set menus=roles.getMenus();
        for (Menus menu:menus){
            System.out.println(menu);
        }
    }
}

 

本文章是我在学习中所记录,如有错误请及时告知,谢谢!!!

你可能感兴趣的:(SpringBoot,Spring,Data,JPA)