springboot集成spring data jpa使用原生sql实现增删改查(gradle)

it2023-08-08  74

JPA

Spring Data JPA 是 spring data 项目下的一个模块。提供了一套基于 JPA标准操作数据库的简化方案。底层默认的是依赖 Hibernate JPA 来实现的。

JPA的出现主要是为了简化持久层开发以及整合ORM技术,结束Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是在吸收现有ORM框架的基础上发展而来,易于使用,伸缩性强。总的来说,JPA包括以下3方面的技术:

ORM映射元数据: 支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系API: 操作实体对象来执行CRUD操作查询语言: 通过面向对象而非面向数据库的查询语言(JPQL)查询数据,避免程序的SQL语句紧密耦合

版本环境

java:jdk-14.0.1 springboot:v2.3.4.RELEASE gradle:gradle-6.7-rc-4 IntelliJ IDEA:2020.1.2 spring-boot-starter-data-jpa:v2.3.4.RELEASE

数据源的配置

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mytest?useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true spring.datasource.username=root spring.datasource.password=rootroot spring.jpa.database=MySQL spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update

create:每次运行程序时,都会重新创建表,故而数据会丢失

create-drop:每次运行程序时会先创建表结构,然后待程序结束时清空表

upadte:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)

validate:运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错

none: 禁用DDL处理

实体类

@NoArgsConstructor @ApiModel(value = "用户实体", description = "用户实体类") @Data @Table(name = "user") @Entity public class User implements Serializable { private static final long serialVersionUID = 4728506793752030545L; @ApiModelProperty(value = "用户名") @Column(name = "name" ) private String name; @JsonIgnore @ApiModelProperty(value = "用户密码") @Column(name = "pass" ) private String pass; @ApiModelProperty(value = "用户年龄") @Column(name = "age" ) private Integer age; @Column(name = "email" ) @ApiModelProperty(value = "用户邮件") private String email; @ApiModelProperty(value = "用户id") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id" ) private Integer id ; }

数据库

create table mytest.user ( id int auto_increment primary key, name varchar(30) not null, pass varchar(30) not null, age int null, email varchar(30) null, constraint user_name_uindex unique (name) );

Repository

@Repository public interface UserRepository extends JpaRepository<User, Integer> { //增 @Transactional(rollbackFor=Exception.class) @Modifying @Query(nativeQuery = true, value ="insert into user(name,pass,age,email) values(?1,?2,?3,?4)") int addUserByName(String name,String pass,int age,String email); //删 @Transactional(rollbackFor=Exception.class) @Modifying @Query(nativeQuery = true, value ="delete from user where name =?1") int deleteUserByName(String name); //改 @Transactional(rollbackFor=Exception.class) @Modifying @Query(nativeQuery = true, value ="update user set pass=?2 where name =?1") int updateUserPassByName(String name,String pass); //查单例 @Query(nativeQuery = true, value ="select id,name,pass,age,email from user where name =?1") User getUserByName(String name); //查集合 @Query(nativeQuery = true, value ="select id,name,pass,age,email from user where age <=?1") List<User> getUsersByAgeMax(int age); }

测试调用

@RunWith(SpringRunner.class) @SpringBootTest public class GradleSpringBootApplicationTests { @Autowired UserRepository userRepository; @Test public void contextLoads() { System.out.println(userRepository.deleteUserByName("lzc")); System.out.println(userRepository.updateUserPassByName("lzc", "960929")); System.out.println(userRepository.getUserByName("lzc").toString()); System.out.println(userRepository.addUserByName("lzc", "123", 123, "aksjlaklsdf")); userRepository.getUsersByAgeMax(30).forEach(System.out::println); } }

遇到的坑

@Modifying和@Transactional

​ 增删改等操作数据库改变的操作必须加@Modifying和@Transactional(rollbackFor=Exception.class)这两个注解。

​ 当我们要通过自已写的更新、插入、删除SQL语句来实现更新、插入、删除操作时,至少需要用两个步骤:1)@Query来注入我们自定义的sql;2)使用@Modifying来标注是一个更新类的自定义语句。

​ @Modifying的主要作用是声明执行的SQL语句是更新(增删改)操作,@Transactional的主要作用是提供事务支持(提供例如隔离性等事务特性,JPA默认会依赖JDBC默认隔离级别)。

​ @Modifying只是声明了这个操作是一个修改操作,但却没有修改这个方法的事务等级,因此这个方法依然不能进行修改操作。只有声明了@Transactional,本质上是声明了@Transactional(readOnly=false),这样覆盖了默认的@Transactional配置便可以执行修改操作了。

最新回复(0)