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中添加依赖

<!-- Spring Data Jpa的启动器 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

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里面添加依赖
  * <dependency>
  *    <groupId>org.projectlombok</groupId>
  *    <artifactId>lombok</artifactId>
  *    <optional>true</optional>
  * </dependency>
  */
@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<User, Long> {

}

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

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

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("123456789@qq.com");
        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<User, Long> {
    //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写)
    // 根据name和年龄进行查询
    List<User> findByName(String name);

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

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

}

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


/**
 * 〈一句话功能简述〉<br> 
 *  Repository    @Query
 *
 * @author admin
 * @create 2019/5/22
 * @since 1.0.0
 */
public interface UsersRepositoryQueryAnnotation extends JpaRepository<User, Long> {

    @Query("from Users where name = ?")
    List<User> queryByNameUseHQL(String name);

    @Query(value = "select * from t_user where name=?",nativeQuery = true)
    List<User> 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<User, Long> {
}

2、测试

    @Test
	public void testCrudRepositorySave() {
		User user = new User();
        user.setUsername("测试1");
        user.setMobilephone("12345678911");
        user.setEmail("1234567@qq.com");
		this.userRepositoryCrudRepository.save(users);
	}

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

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

	@Test
	public void testCrudRepositoryFindAll() {
		List<User> list= (List<Users>) 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<User, Long> {

}

2、测试

    @Test
	public void testPagingAndSortingRepositorySort() {
		//Order	定义了排序规则
		Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort=new Sort(order);
		List<User> list = (List<User>) 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<User> page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List<Users> 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<Users> page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List<Users> list=page.getContent();
		for (User user : list){
			System.out.println(user);
		}
	}

4)JpaRepository接口

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

1、dao层接口编写

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

}

2、测试

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

5)JPASpecificationExecutor接口

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

1、dao层接口编写

public interface UserRepositorySpecification extends JpaRepository<User, Long>,JpaSpecificationExecutor<User> {
}

2、测试

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

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

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

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

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

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

		Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"lid"));
		List<User> 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> 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<User, Long> {

}

3)测试

/**
 * 〈一句话功能简述〉<br> 
 * 多对多的关联关系的测试
 *
 * @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> 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> 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> 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> menus=new HashSet<>();

2)dao层接口

public interface RolesRepository extends JpaRepository<Roles,Integer> {
}

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> menus=roles.getMenus();
        for (Menus menu:menus){
            System.out.println(menu);
        }
    }
}

 

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值