我们继续使用上一章的环境。SpringBoot之Spring Data JPA入门学习
一、自动生成数据
我们修改一下实体 增加了几个注解:
@CreationTimestamp 自动生成创建时间。
@UpdateTimestamp 自动生成更新时间。
使用这两个注解我们还需要在类上加上两个注解@DynamicInsert和@DynamicUpdate
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: 用户实体
*/
@Entity
@Table(name = "t_user")
@Data
@DynamicInsert
@DynamicUpdate
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 姓名
*/
@Column(name = "name")
private String name;
/**
* 年龄
*/
@Column(name = "age")
private Integer age;
/**
* 余额
*/
@Column(name = "money")
private BigDecimal money;
/**
* 是否删除
*/
@Column(columnDefinition = "bit default 0 COMMENT '是否删除'")
private Boolean deleted;
/**
* 创建时间
*/
@Column(name = "create_at")
@CreationTimestamp
private Date createAt;
/**
* 更新时间
*/
@Column(name = "update_at")
@UpdateTimestamp
private Date updateAt;
}
测试:
import com.example.quartzdemo.entity.User;
import com.example.quartzdemo.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.util.List;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: JPA的使用
*/
@SpringBootTest
public class JpaTest {
@Autowired
private UserRepository userRepository;
/**
* 新增数据
*/
@Test
void test1() {
User user = new User();
user.setName("张三");
user.setMoney(BigDecimal.TEN);
user.setAge(20);
userRepository.save(user);
}
}
控制台显示sql执行语句
Hibernate: insert into t_user (age, create_at, money, name, update_at) values (?, ?, ?, ?, ?)
我们查看数据库,数据表自动生成了创建时间和更新时间,deleted字段使用了默认值。
我们修改数据,更新时间也相应的进行了修改
/**
* 修改数据
*/
@Test
void test4() {
// 修改ID为1的数据
User user = userRepository.findById(1L).get();
user.setAge(21);
userRepository.save(user);
}
Hibernate: select user0_.id as id1_1_0_, user0_.age as age2_1_0_, user0_.create_at as create_a3_1_0_, user0_.deleted as deleted4_1_0_, user0_.money as money5_1_0_, user0_.name as name6_1_0_, user0_.update_at as update_a7_1_0_ from t_user user0_ where user0_.id=?
Hibernate: select user0_.id as id1_1_0_, user0_.age as age2_1_0_, user0_.create_at as create_a3_1_0_, user0_.deleted as deleted4_1_0_, user0_.money as money5_1_0_, user0_.name as name6_1_0_, user0_.update_at as update_a7_1_0_ from t_user user0_ where user0_.id=?
Hibernate: update t_user set age=?, update_at=? where id=?
二、数据修改
如果我们不是通过先查询出数据,再修改对应值的情况,有可能会导致一些没有要修改的数据从有值变没有数值了,会导致出现想不到的结果。如果我们只想更新某个元素,而不是先查询数据再修改的情况,那么我们可以在数据层实现自定义的操作。
import com.example.quartzdemo.entity.User;
import com.example.quartzdemo.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.util.List;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: JPA的使用
*/
@SpringBootTest
public class JpaTest {
@Autowired
private UserRepository userRepository;
/**
* 修改数据
*/
@Test
void test4() {
// 修改ID为1的数据
User user = new User();
user.setId(1L);
user.setName(null);
user.setAge(21);
userRepository.save(user);
}
}
如果我们只更新其他的一些数据,执行后我们查看数据库,一些原来的数据被清空掉了,这不是我们想要的结果。
Hibernate: select user0_.id as id1_1_0_, user0_.age as age2_1_0_, user0_.create_at as create_a3_1_0_, user0_.deleted as deleted4_1_0_, user0_.money as money5_1_0_, user0_.name as name6_1_0_, user0_.update_at as update_a7_1_0_ from t_user user0_ where user0_.id=?
Hibernate: update t_user set age=?, create_at=?, deleted=?, money=?, name=?, update_at=? where id=?
我们在数据层创建自定义的操作方法
import com.example.quartzdemo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: 用户数据层
*/
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根据ID修改用户姓名和年龄
*
* @param name 姓名
* @param age 年龄
* @param id ID
*/
@Modifying
@Query("update User u set u.name=?1,u.age=?2 where u.id=?3")
void updateNameAndAgeById(String name, Integer age, Long id);
}
涉及到数据修改、删除操作,需要使用 @Modifying
注解。如果是查询就是要@Query注解书写语句就可以了。
/**
* 修改数据
*/
@Test
@Transactional
@Rollback(value = false)
void test4() {
// 修改ID为1的数据
userRepository.updateNameAndAgeById(null,21,1L);
}
Hibernate: update t_user set name=?, age=? where id=?
我们在数据库看到现在可以实现只更新某些元素了,其他元素没有受到影响。
三、多种查询方式
我们在使用查询的时候,批量插入多条测试数据
insert into t_user(id,name,age,money,deleted,create_at,update_at)
values
(1, '一qxblog',25,100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(2, '一qx2',22, 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(3, '一qx3',23, 300, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(4, '一qx4',24, 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(5, '一qx5',28, 500, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(6, 'Batch 一qxblog',29, 100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(7, 'Batch 一qxblog 2',30, 100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(8, 'Batch 一qx 3',35, 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(9, 'Batch 一qx 4',45, 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(10, 'batch 一qx5',29, 1498, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:58'),
(11, 'batch 一qx6',31, 1498, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:58'),
(12, 'batch 一qx7',32, 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
(13, 'batch 一qx8',34, 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40');
1.根据ID查询
import com.example.quartzdemo.entity.User;
import com.example.quartzdemo.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: JPA的使用
*/
@SpringBootTest
public class JpaTest {
@Autowired
private UserRepository userRepository;
/**
* 根据ID查询
*/
@Test
void test1(){
Optional<User> userOptional = userRepository.findById(1L);
// User(id=1, name=一qxblog, age=25, money=100.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)
System.out.println(userOptional.get());
}
}
2.根据用户名查询
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根据用户名查询
* @param name 用户名
*/
User findByName(String name);
/**
* 根据用户名查询
* @param name 用户名
* @return
*/
User queryByName(String name);
}
import com.example.quartzdemo.entity.User;
import com.example.quartzdemo.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: JPA的使用
*/
@SpringBootTest
public class JpaTest {
@Autowired
private UserRepository userRepository;
/**
* 根据ID查询
*/
@Test
void test1() {
User user1 = userRepository.queryByName("一qx2");
// 输出User(id=2, name=一qx2, age=22, money=200.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)
System.out.println(user1);
User user2 = userRepository.findByName("一qx2");
// 输出User(id=2, name=一qx2, age=22, money=200.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)
System.out.println(user2);
}
}
3.like查询
import com.example.quartzdemo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: 用户数据层
*/
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根据用户名查询
* @param name 用户名
*/
User findByName(String name);
/**
* 根据用户名查询
* @param name 用户名
* @return
*/
User queryByName(String name);
/**
* 根据用户名模糊查询
* @param name 用户名
*/
List<User> findByNameLike(String name);
}
import com.example.quartzdemo.entity.User;
import com.example.quartzdemo.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* @author qinxun
* @date 2023-06-07
* @Descripion: JPA的使用
*/
@SpringBootTest
public class JpaTest {
@Autowired
private UserRepository userRepository;
/**
* 根据ID查询
*/
@Test
void test1() {
List<User> userList = userRepository.findByNameLike("%qx%");
System.out.println(userList);
}
}
查询后返回
Hibernate: select user0_.id as id1_1_, user0_.age as age2_1_, user0_.create_at as create_a3_1_, user0_.deleted as deleted4_1_, user0_.money as money5_1_, user0_.name as name6_1_, user0_.update_at as update_a7_1_ from t_user user0_ where user0_.name like ? escape ?
[User(id=1, name=一qxblog, age=25, money=100.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=2, name=一qx2, age=22, money=200.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=3, name=一qx3, age=23, money=300.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=4, name=一qx4, age=24, money=400.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=5, name=一qx5, age=28, money=500.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=6, name=Batch 一qxblog, age=29, money=100.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=7, name=Batch 一qxblog 2, age=30, money=100.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=8, name=Batch 一qx 3, age=35, money=200.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=9, name=Batch 一qx 4, age=45, money=200.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=10, name=batch 一qx5, age=29, money=1498.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), User(id=11, name=batch 一qx6, age=31, money=1498.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), User(id=12, name=batch 一qx7, age=32, money=400.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), User(id=13, name=batch 一qx8, age=34, money=400.00, deleted=false, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
其他的一些常用的JPA用法
方法名 | 说明 | 等效sql |
---|---|---|
findByXxx | 表示根据列Xxx 等于传参构建sql | where xxx= ? |
findByXxxAndYyy | 根据多个列进行查询 | where xxx=? and yyy=? |
findByXxxOrYyy | 根据多个列实现or查询 | where xxx=? or yyy=? |
findByXxxLike | like查询,需要注意查询条件中加% | where xxx like |
findByXxxIn | in查询 | where Xxx in () |
findByXxxGreaterThan | 大于 | where xxx > ? |
findByXxxGreaterThanEqual | 大于等于 | where xxx >= ? |
findByXxxLessThan | 小于 | where xxx < ? |
findByXxxLessThanEqual | 小于等于 | where xxx <= ? |
findByXxxNot | 不等于 | where xxx != ? |
findByXxxIsBetween | between查询 | where xxx between ? and ? |
OrderByXxxDesc | 排序 | order by xxx desc |
topN | 分页,表示获取最前面的n条 | limit n |