6、Spring Data JPA 之 单表的CRUD操作
实体类
/**
* 1.实体类和表的映射关系
* @Entity
* @Table
* 2.类中属性和表中字段的映射关系
* @Id
* @GeneratedValue
* @Column
*/
@Entity
@Table(name="users")
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Integer userId;
@Column(name = "user_name")
private String userName;
@Column(name = "gender")
private String gender;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Users{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
接口
/**
* 符合Spring Data Jpa 的 dao层接口规范
* JpaRepository<操作的实体类类型,实体类中主键属性的类型>
* #封装了基本CRUD操作
* JpaSpecificationExecutor <操作的实体类类型>
* #封装了复杂查询(分页)
*/
public interface UsersDao extends JpaRepository<Users, Integer>,JpaSpecificationExecutor<Users>{
}
单表的基础CRUD操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
public class UsersDaoTest {
@Autowired
private UsersDao usersDao;
/**
* 根据id查询(立即加载)
*/
@Test
public void testFindOne(){
Users user = usersDao.findOne(1);
System.out.println(user);
}
/**
* save:保存或更新
* 根据传递的对象是否存在主键id,
* 如果没有id主键属性,保存
* 存在id主键属性,根据id查询数据,更新数据
* (SpringDataJPA内部会根据id查询是否存在该数据,有才更新)
*/
@Test
public void testSave(){
Users users = new Users();
users.setUserName("小陈");
usersDao.save(users);
}
/**
* 如果直接更新某条数据的某个字段这其他没有改的字段会变成null
* 所以执行更新时,先查询再更新
*/
@Test
public void testUpdate(){
Users users = new Users();
users.setUserId(4);
users.setUserName("小张");
usersDao.save(users);
}
/**
* 删除
*/
@Test
public void testDelete(){
usersDao.delete(3);
}
/**
* 查询所有
*/
@Test
public void testFindAll(){
List<Users> list = usersDao.findAll();
for (Users users: list
) {
System.out.println(users);
}
}
/**
* 使用count函数进行查询
*/
@Test
public void testCount(){
long count = usersDao.count(); //查询全部的客户数量
System.out.println(count);
}
/**
* 判断id为4的用户是否存在
* 1.可以查询以下id为4的客户
* 如果值为空,代表不存在,如果不为空,则存在
* 2.判断数据库中id为4的客户的数量
* 如果数量为0,表示不存在,大于0则存在
*/
@Test
public void testExists(){
boolean isExists = usersDao.exists(4);
System.out.println(isExists);
}
/**
* 根据id从数据库查询
* @Transactional: 保证getOne正常运行
* findOne:
* em.find() 立即加载
* getOne:
* em.getReference 延迟加载
* 返回的是一个客户的动态代理对象
* 什么时候用,什么时候查询
*/
@Test
@Transactional
public void testGetOne(){
Users user = usersDao.getOne(4);
System.out.println(user);
}
}
单表的JPQL查询
JPQL方法需要自己在接口上定义抽象方法
------- 抽象方法
/**
* 根据用户名查询用户
* 使用jpql语句,使用@Query注解
* select * from user where user_name = ?
* @param username
* @return
*/
@Query(value = "from com.example.pojo.Users where userName = ?")
List<Users> findUsersByUsername(String username);
------ 测试
/**
* 通过用户名查询用户
*/
@Test
public void testGetUserByName(){
List<Users> list = usersDao.findUsersByUsername("小白");
System.out.println(list);
}
--------------- 抽象方法
/**
* 根据用户名称和用户id查询用户
* select from users where usrename = ? and userId = ?
*
* 对于多个占位符参数
* 赋值时,默认情况下,占位符的位置需要和方法参数总的位置保持一致
*/
@Query("from com.example.pojo.Users where userName=? and userId=?")
Users findUsersByUserNameAndUserId(String Name, Integer id);
-------------- 测试
/**
* 多占位符的赋值
*/
@Test
public void testGetUserByNameAndUserId(){
Users user = usersDao.findUsersByUserNameAndUserId("小白", 2);
System.out.println(user);
}
---------- 抽象方法
/**
* 如果占位符取值与参数顺序不符时,需要在占位符后添加取值位置
* @param Name
* @param id
* @return
*/
@Query("from com.example.pojo.Users where userName=?2 and userId=?1")
Users findUsersByUserNameAndUserId2(Integer id, String Name);
----------测试
/**
* 多占位符的赋值
*/
@Test
public void testGetUserByNameAndUserId2(){
Users user = usersDao.findUsersByUserNameAndUserId2(2,"小白");
System.out.println(user);
}
---------- 抽象方法
/**
* 使用JPQL完成更新操作
* 根据id更新用户的名称
* update users set user_name = ? where user_id = ?
* @Modifying
* 当前执行的是一个更新操作
*/
@Query("update com.example.pojo.Users set userName = ? where userId = ?")
@Modifying
void updateUsernameByUserId(String name, Integer id);
---------- 测试
/**
* 使用JPQL完成更新操作
* springDataJpa中使用jpql完成更新、删除操作
* 需要手动添加书屋的支持
* 默认会执行结束之后,回滚事务
* @Rollback 设置是否自动回滚(如果@Transactional注解标注在接口方法上,则不需要配置@Rollback注解)
*/
@Test
@Transactional
@Rollback(value = false)
public void testUpdateCustomer(){
usersDao.updateUsernameByUserId("小陈",2);
}
SQL语句查询
Spring Data JPA 同样支持原生sql的CRUD操作,方法由自己定义在到接口中
----------- 抽象方法
/**
* 使用sql的形式查询
* 查询全部的用户 select * from users
* nativeQuery = true就是该查询为sql查询
*/
@Query(value = "select * from users", nativeQuery = true)
List<Object []> sqlQueryFindAllUsers();
------------ 测试
/**
* sql语句查询所有
*/
@Test
public void testSqlQueryFindAllUsers(){
List<Object[]> list = usersDao.sqlQueryFindAllUsers();
for (Object[] obj: list
) {
System.out.println(Arrays.toString(obj));
}
}
------------ 抽象方法
/**
* 模糊查询
* 使用sql的形式查询
* 查询全部的用户 select * from users
* nativeQuery = true就是该查询为sql查询
*/
@Query(value = "SELECT * FROM users WHERE user_name LIKE ?", nativeQuery = true)
List<Object []> sqlQueryFindUsers(String name);
------------ 测试
/**
* sql语句模糊查询
*/
@Test
public void testSqlQueryFindUsers(){
List<Object[]> list = usersDao.sqlQueryFindUsers("%小%");
for (Object[] obj : list
) {
System.out.println(Arrays.toString(obj));
}
}
方法名称规则查询
同样需要在接口中定义该方法
提示
/**
* 方法名称规则查询
* 是对jpql查询,更加深入的一层封装,我们只需要按照SpringDataJpa提供的方法名称
* 规则定义方法,不需要再去配置jpql语句,完成查询
* SpringDataJpa 的运行阶段会根据方法名称进行解析,
* findBy + 实体类属性名称(条件查询)
* findBy + 实体类属性名称 + 查询方式(like,is null,between等)
* findBy + 实体类属性名 + 查询方式 + 多条件连接符(and|or) + 实体类属性 + 查询方式
* 模糊匹配需要写查询方式,精准匹配可以不写
*/
------------- 抽象方法
/**
* 方法名称规则查询
* find 查询
* 对象中的属性名称(首字母大写)作为查询条件
* 如:findByUserName 以userName属性为查询条件,进行条件查询
* 注意:方法名称规则查询不需要添加@Query注解
*/
Users findByUserName(String name);
------------- 测试
/**
* 条件查询
* 用户名作为条件进行查询
*/
@Test
public void testFindByUserName(){
Users user = usersDao.findByUserName("小黑");
System.out.println(user);
}
------------ 抽象方法
/**
* 模糊查询
* 对用户名进行模糊查询
* @return
*/
List<Users> findByUserNameLike(String name);
----------- 测试
/**
* 模糊查询
* 通过用户名进行模糊查询
*/
@Test
public void testFindByUserNameLike(){
List<Users> list = usersDao.findByUserNameLike("小%");
for (Users user : list
) {
System.out.println(user);
}
}
------------ 抽象方法
/**
* 多条件查询
* 用户姓名模糊查询和id精准配置
* userName是模糊查询必须写上查询方式(like)
* userId是精准匹配不写写查询方式
*/
Users findByUserNameLikeAndUserId(String name, Integer id);
------------- 测试
@Test
public void testFindByUserNameLikeAndUserId(){
Users user = usersDao.findByUserNameLikeAndUserId("小%", 1);
System.out.println(user);
}