SpringBoot整合Spring Data JPA

SpringBoot整合Spring Data JPA

一、Spring Data JPA介绍

Spring Data 就是提供了一个操作数据的框架。而Spring Data JPA就是Spring Data 框架下的一个基于JPA标准操作数据的模块。

简化操作持久层代码,只要编写接口即可。

二、整合Spring Data JPA

pom.xml

   <dependencies>
  		<!-- web启动器 -->
  		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- thymeleaf启动器的坐标 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- jpa启动器 -->
		<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>
		<!-- 数据库连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.2.5</version>
		</dependency>
  </dependencies>

添加application.properties

spring.datasource.dirverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
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

实体类

/**
 * 实体类
 * @author 24957
 *
 */
@Entity//标记实体类
@Table(name="t_users")//数据库中表名
public class Users {

	@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;
	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;
	}
	
}

dao层接口

/**
 * 
 * 第一个参数 T:指的是实体类的类型
 * 第二个参数:ID:指的是实体类主键的数据类型
 * @author 24957
 *
 */
public interface UsersDao extends JpaRepository<Users, Integer> {

}

启动类

/**
 * 启动类
 * @author 24957
 *
 */
@SpringBootApplication
public class App {

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

测试类

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

	@Autowired
	private UsersDao usersDao;
	@Test
	public void testSave() {
		Users users = new Users(); 
		users.setName("庞杰");
		users.setAge(22);
		users.setAddress("天津武清");
		usersDao.save(users);//save()方法来自于继承的接口中
	}
}

save()方法

/**
	 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
	 * entity instance completely.
	 *
	 * @param entity must not be {@literal null}.
	 * @return the saved entity; will never be {@literal null}.
	 * @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
	 */
	<S extends T> S save(S entity);

运行测试类:成功后会在数据库中创建好“t_users”表,并且将Users数据添加到表中。

控制台输出:

Hibernate: insert into t_users (address, age, name) values (?, ?, ?)

三、Spring Data JPA提供核心接口

Repository接口

CrudRepository接口

PagingAndSortingRepository接口

JpaRepository接口

JPASpecificationExecutor接口

1、Repository接口

提供了方法名称命名查询方式

接口

/**
 * 
 * 方法名称命名查询方式
 * @author pangjie
 *
 */
public interface UsersRepository extends Repository<Users,Integer> {

	/*
	 * 方法命名:驼峰式,find+By+查询条件
	 */
	List<Users> findByName(String name);
}

测试类

@Test
	public void testFindByName() {
		List<Users> findByName = usersRepository.findByName("庞杰");
		System.out.println(findByName.toString());
	}

提供了基于@Query注解查询与更新

接口

/**
 * 
 * @Query
 * @author pangjie
 *
 */
public interface UsersQuery extends Repository<Users, Integer> {

	@Query(value="select * from t_users where name=?",nativeQuery = true)
	List<Users> queryByNameUseHQL(String name);
	
	@Query(value="update t_users set name=? where id=?",nativeQuery = true)
	@Modifying//进行更新操作
	int updateUsers(String name,Integer id);
}

测试类

@Test
	public void testQueryByName() {
		List<Users> list = usersQuery.queryByNameUseHQL("谢知松");
		for (Users users : list) {
			System.out.println(users);
		}
	}
	@Test
	@Transactional
	@Rollback(false)//取消自动回滚
	public void testUpdateUsers() {
		int updateUsers = usersQuery.updateUsers("谢天龙", 2);
		if(updateUsers>0) {
			System.out.println("success");
		}else {
			System.out.println("失败");
		}
	}

2、CrudRepository接口

主要完成增删改查操作

CrudRepository接口继承了Repository接口

接口

/**
 * CrudRepository接口
 * @author pangjie
 *
 */
public interface UsersCrudRepository extends CrudRepository<Users, Integer> {

}

测试

	 /**
	  * 添加、修改方法都是save(对象)
	  * 如果是新对象则进行添加操作
	  * 如果是数据库中存在的对象则进行修改操作。
	  */
	@Test
	public void  testCrudSave() {
	
		Users users = new Users();
		users.setId(8);
		users.setAddress("武当山");
		users.setAge(102);
		users.setName("张翠山");
		Users users2 = usersCrudRepository.save(users);
	}
	/**
	 * 查询操作
	 * findAll--查询全部
	 * findById--查询一条数据
	 */
	@Test
	public void testFindOne() {
		Iterable<Users> findAll = usersCrudRepository.findAll();
		for (Users users : findAll) {
			System.out.println(users);
		}
	}
	/**
	 * 删除操作
	 */
	@Test
	public void testDelete() {
		usersCrudRepository.deleteById(8);
	}

3、PagingAndSortingRepository接口

特点:提供了分页与排序的操作。

继承了CrudRepository接口

分页加排序

接口

/**
 * PagingAndSortingRepository 分页,排序
 * @author pangjie
 *
 */
public interface UsersSortAndPaging extends PagingAndSortingRepository<Users, Integer> {

}

测试类

/**
	 * 分页+排序
	 */
	@Test
	public void testPaging() {
		//Order对象,定义排序规则
		Order order =  new Order(Direction.DESC, "id");
		//Sort对象封装了排序规则
		Sort sort  = new Sort(order);
		Pageable pagable = new PageRequest(0, 2, sort);
		Page<Users> page = this.usersSortAndPaging.findAll(pagable);
		List<Users> list = page.getContent();
		for (Users users : list) {
			System.out.println(users);
		}
	}

4、JpaRepository接口(用的比较多)

JpaRepository接口继承了PagingAndSortingRepository接口

对继承的父接口中的返回值进行适配。(无需进行强制类型装换)

5、JPASpecificationExecutor接口

提供了多条件查询,并且可以在查询中添加排序与分页。

此接口完全独立存在,通常与JpaRepository配合使用

/**
 * JpaSpecificationExecutor 接口
 * @author pangjie
 *
 */
public interface UserJPASpecificationExecutor extends JpaRepository<Users, Integer>,JpaSpecificationExecutor<Users> {

}

/**
	 * 单条件查询
	 */
	@Test
	public void testSpecifiation() {
		/**
		 * Specification<Users>() 用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			/**
			 * Predicate:封装了单个的查询条件
			 * Root<Users> root 查询对象属性的封装
			 * CriteriaQuery<?> query 封装了查询中的各个部分的信息
			 * CriteriaBuilder criteriaBuilder 定义不同的查询条件。
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				/**
				 * equal(root,query)
				 * 第一个参数:查询条件的属性、
				 * 第二个参数:条件的值
				 */
				Predicate predicate = criteriaBuilder.equal(root.get("name"),"庞杰");
				
				return predicate;
			}
		};
		List<Users> list = userSpecification.findAll(spec);
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	/**
	 * 多条件查询
	 */
	@Test
	public void testSpecifiation2() {
		/**
		 * Specification<Users>() 用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			/**
			 * Predicate:封装了单个的查询条件
			 * Root<Users> root 查询对象属性的封装
			 * CriteriaQuery<?> query 封装了查询中的各个部分的信息
			 * CriteriaBuilder criteriaBuilder 定义不同的查询条件。
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				
				List<Predicate> list = new ArrayList<>();
				list.add(criteriaBuilder.equal(root.get("name"), "庞杰"));
				list.add(criteriaBuilder.equal(root.get("age"), 22));
				
				Predicate[] predicate = new Predicate[list.size()];
				Predicate and = criteriaBuilder.and(list.toArray(predicate));
				return and;
			}
		};
		List<Users> list = userSpecification.findAll(spec);
		for (Users users : list) {
			System.out.println(users);
		}
	}

/**
	 * 多条件查询方法二
	 */
	@Test
	public void testSpecifiation3() {
		/**
		 * Specification<Users>() 用于封装查询条件
		 */
		Specification<Users> spec = new Specification<Users>() {
			/**
			 * Predicate:封装了单个的查询条件
			 * Root<Users> root 查询对象属性的封装
			 * CriteriaQuery<?> query 封装了查询中的各个部分的信息
			 * CriteriaBuilder criteriaBuilder 定义不同的查询条件。
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				/*
				 * List<Predicate> list = new ArrayList<>();
				 * list.add(criteriaBuilder.equal(root.get("name"), "庞杰"));
				 * list.add(criteriaBuilder.equal(root.get("age"), 22));
				 * 
				 * Predicate[] predicate = new Predicate[list.size()];
				 */
				
				Predicate and = criteriaBuilder.or(criteriaBuilder.and(criteriaBuilder.equal(root.get("name"), "庞杰"),criteriaBuilder.equal(root.get("age"), 22)),criteriaBuilder.equal(root.get("id"), 2));
				return and;
			}
		};
		//Sort sort  = new Sort(new Order(Direction.DESC,"id"));
		List<Users> list = userSpecification.findAll(spec);
		for (Users users : list) {
			System.out.println(users);
		}
	}
	
	

6、关联映射操作

一对多:

角色与用户:一对多

角色:一

用户:多

修改Users,添加以下内容

	@ManyToOne
	@JoinColumn(name="roles_id") //维护外键
	private Roles roles;

添加Roles类

/**
 * 实体类
 * @author pangjie
 *
 */
@Entity//标记实体类
@Table(name="t_roles")//数据库中表名
public class Roles {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="rolesid")
	private Integer rolesid;
	@Column(name="rolesname")
	private String rolesname;
	@OneToMany(mappedBy = "roles")//与Users对象对应。
	private Set<Users> users = new HashSet<>();
	public Integer getRolesid() {
		return rolesid;
	}
	public void setRolesid(Integer rolesid) {
		this.rolesid = rolesid;
	}
	public String getRolesname() {
		return rolesname;
	}
	public void setRolesname(String rolesname) {
		this.rolesname = rolesname;
	}
	public Set<Users> getUsers() {
		return users;
	}
	public void setUsers(Set<Users> users) {
		this.users = users;
	}
	
}

测试一对多的关联关系

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class OneToMoney {
	@Autowired
	private UsersDao usersDao;

	@Test
	public void testSave() {
	//创建用户
	Users users  = new Users();
	users.setAddress("青岛");
	users.setAge(40);
	users.setName("黄渤");
	//创建角色
	Roles roles = new Roles();
	roles.setRolesname("管理员");
	//关联
	roles.getUsers().add(users);//将用户放到角色的集合中
	users.setRoles(roles);
	//保存
	usersDao.save(users);
	}
}

修改Users实体类

	@ManyToOne(cascade = CascadeType.PERSIST)
	@JoinColumn(name="roles_id") //维护外键
	private Roles roles;

多对多关联

角色与菜单的多对多关系

角色:多方

菜单:多方

Roles(角色)实体添加

@ManyToMany
	/*@JoinTable映射中间表
	 * joinColumns 当前表的主键所关联的中间表的外键
	 */
	@JoinTable(name = "t_roles_menus",joinColumns = @JoinColumn(name="role_id"),inverseJoinColumns = @JoinColumn(name="menus_id"))
	private Set<Menus> menus = new HashSet<Menus>();

添加Menus实体

@Entity//标记实体类
@Table(name="t_menus")//数据库中表名
public class Menus {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "menusid")
	private Integer menusid;
	@Column(name = "menusname")
	private String menusname;
	@Column(name = "menusurl")
	private String menusurl;
	@Column(name = "fatherid")
	private Integer fatherid;
	
	@ManyToMany(mappedBy = "menus")
	private Set<Roles> roles = new HashSet<>();
	public Integer getMenusid() {
		return menusid;
	}
	public void setMenusid(Integer menusid) {
		this.menusid = menusid;
	}
	public String getMenusname() {
		return menusname;
	}
	public void setMenusname(String menusname) {
		this.menusname = menusname;
	}
	public String getMenusurl() {
		return menusurl;
	}
	public void setMenusurl(String menusurl) {
		this.menusurl = menusurl;
	}
	public Integer getFatherid() {
		return fatherid;
	}
	public void setFatherid(Integer fatherid) {
		this.fatherid = fatherid;
	}
	
}

测试多对多关联关系

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class ManyToMany {

	@Autowired
	private RolesRepository rolesRepository;
	@Test
	public void testSave() {
		//创建角色
		Roles roles = new Roles();
		roles.setRolesname("项目经理");
		//创建菜单
		Menus menus = new Menus();
		menus.setMenusname("项目系统");
		menus.setFatherid(0);
		Menus menus2 = new Menus();
		menus2.setMenusname("项目菜单");
		menus2.setFatherid(1);
		
		//关联
		roles.getMenus().add(menus);
		roles.getMenus().add(menus2);
		menus.getRoles().add(roles);
		menus2.getRoles().add(roles);
		//保存
		rolesRepository.save(roles);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值