SpringDataJPA ORM

本文介绍了SpringDataJPA作为JPA的封装,如何与SpringBoot进行整合。通过添加依赖,配置数据库连接,设置DDL-Auto策略,以及创建@Entity和@Repository接口,实现无需编写SQL的CRUD操作。同时,文章讨论了DDL-Auto的各种模式,并展示了使用@Query进行复杂查询的方法,以及如何实现排序和分页功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用Hibernate 的 JPA 技术实现。Hibernate 和Mybatis都是ORM框架,所以可以将SpringDataJPA理解为Mybatis。

二、SpringBoot整合JPA 

更多用法参考官网:Spring Data JPA

1.1依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

1.2配置

spring:  
 jpa:
    hibernate:
      #更新或者创建数据表结构
      ddl-auto: update
      #控制台显示SQL
    show-sql: true
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=tianya
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
server.port=8010
logging.level.org.springframework=error

#spring.jpa.generate-ddl=
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.type=trace
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.jdbc.batch_size=50
logging.level.org.hibernate.type.descriptor.sql=trace

ddl-auto说明

在jpa中ddl-auto一共有四种:
1、ddl-auto:create ----每次运行该程序,没有表格会新建表格,表内有数据会清空;
2、ddl-auto:create-drop ----每次程序结束的时候会清空表
3、ddl-auto:update ---- 每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
4、ddl-auto: validate ---- 运行程序会校验数据与数据库的字段类型是否相同,不同会报错。

一般选择validate/update/none,绝对不能选 create, create-drop,update能帮助建表。
如果希望实体类发生改动而数据库表做出相应的更改且不破坏数据库现有的数据,要将spring.jpa.hibernate.ddl-auto属性值设置为update
这里还有一点,就算把ddl-auto设置成update值,也不能识别对表结构的所有更改,往往只能识别出增加的字段,比如修改字段名,修改字段类型或者删除一个字段都是不能够识别的。

1.3代码

@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "tbl_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class User {
    @Id //这是一个主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
    private Integer id;
    @Column(name = "last_name",length = 50) //这是和数据表对应的一个列
    private String lastName;
    @Column //省略默认列名就是属性名
    private String email;
}
//继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}

1.4无须写SQL

增删改查

Repository相当于Mybatis中的Mapper层,可以在里面写crud接口,所以只需要继承JpaRepository类即可,其它的扩展类还有MongoRepository、CrudRepository、CrudRepository等。举个栗子如下图:

JpaRepository.java

更多介绍参考官网:Spring Data JPA 

 

注解

关键字

 

1.5需要写SQL

要想查询全部字段可以用 sellect 实体名 这里省略了value ,参数使用了占位置符 ?1 代表第一个参数 ? 2 代表第二个

HQL方式

public interface UserRepository extends JpaRepository<User, Long> {
 
   @Query("select u from User u where u.emailAddress = ?1")
   User findByEmailAddress(String emailAddress);

   //如果是更新或者删除操作,方法上面要加@Modifying      默认开启的事务只是可读的,更新操作加入@Modifying 就会关闭可读
    @Modifying
    @Transactional
    @Query("update CardConfig  set cardStatus=?1 where  id in ?2")
    void updateCardStatus( Integer status,List<Integer> listIds);

   // @Param 代替参数占位符,  hql或者sql里就用  :firstname替换   方法里的参数顺序可以打乱
   @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
   User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                 @Param("firstname") String firstname);

   //返回字段 组成新的entity返回 类名必须是全写的
   @Query(value="select new com.hikvision.metro.modules.repository.entity.CameraIndexs(c.preOneCameraIndexcode, c.preTwoCameraIndexcode, c.backOneCameraIndexcode) from StationDeviceConfig c")
    List<CameraIndexs> getAllCameraIndexs();


}

SQL方式

  
    @Modifying
    @Query(value="select status from  t_station_device_config where pre_one_camera_indexcode=?1",nativeQuery = true)
    List<Integer> findStatusByPreOneCameraIndexcode(String index);


    @Query(value="select radar_indexcode from  t_station_device_config",nativeQuery = true)
    List<String> getAllRadarIndex();


1.6排序与分页

Service层

@Repository
public interface CardConfigRepository extends JpaRepository<CardConfig,Integer>, JpaSpecificationExecutor {
}

构造Pageable排序

第一种方式:
 Sort sort = new Sort(Sort.Direction.DESC, "preDrawIssue").and(new Sort(Sort.Direction.ASC, "regionCode"));
 Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
第二种方式:
       List<Sort.Order> orders=new ArrayList<>();
         orders.add(new Sort.Order(Sort.Direction.DESC,"preDrawIssue"));
         orders.add(new Sort.Order(Sort.Direction.ASC,"regionCode"));
          Sort sort  = Sort.by(orders);
    Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort); 

传入Pageable调用

 public BaseResult findAll(Pageable pageable, BaseSearch baseSearch) {
        List<CardInfo> passInfoBos = new ArrayList<>();
        BasePage<CardInfo> basePage = new BasePage<>();
        try {
            Specification querySpeci = (root, criteriaQuery, criteriaBuilder) -> {
                List<Predicate> predicates = Lists.newArrayList();
                if (!StringUtils.isEmpty(baseSearch.getPersonName())) {
                    predicates.add(criteriaBuilder
                            .like(root.get("personName"), "%" + baseSearch.getPersonName() + "%"));
                }
                if (!StringUtils.isEmpty(baseSearch.getCardNo())) {
                    predicates.add(criteriaBuilder
                            .like(root.get("cardId"), "%" + baseSearch.getCardNo() + "%"));
                }
                if (baseSearch.getType() != null) {
                    predicates.add(criteriaBuilder
                            .equal(root.get("cardType"), baseSearch.getType()));
                }

                if (baseSearch.getStatus() != null) {
                    predicates.add(criteriaBuilder
                            .equal(root.get("cardStatus"), baseSearch.getStatus()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            };
			//继承了JpaSpecificationExecutor的才会有这个接口
            Page<CardConfig> page = cardConfigRepository.findAll(querySpeci, pageable);
            if (page != null) {
                for (CardConfig info : page.getContent()) {
                    CardInfo cardInfo = new CardInfo();
                    cardInfo.convertFromCardConfig(info);
                    passInfoBos.add(cardInfo);
                }
                basePage.setList(passInfoBos);
                basePage.setTotal(page.getTotalElements());
                basePage.setTotalPages(page.getTotalPages());
                basePage.setPageSize(page.getSize());
                basePage.setPageNo(page.getNumber() + 1);
                //LOGGER.info("分页查询卡片列表成功");
            } else {
                return BaseResult.fail(CommonErrorCode.SYSTEM_INTERNAL_ERROR.getCode(), CommonErrorCode.SYSTEM_INTERNAL_ERROR.getMsg());
            }
        } catch (BusinessException e) {
            throw e;
        } catch (AuthorizationException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.errorWithErrorCode(ErrorCode.CARD_CONFIG_QUERY_ERROR.getCode(), ErrorCode.CARD_CONFIG_QUERY_ERROR.getChinaMessage(), e);
            throw new MetroBusinessException(ErrorCode.CARD_CONFIG_QUERY_ERROR, e);
        }
        return new BaseResult(0, "0", "成功", basePage);
    }

### Spring Data JPA 是否属于 ORM 技术及其工作原理 Spring Data JPA 属于一种基于对象关系映射(Object-Relational Mapping, ORM)的技术,但它本身并不是一个独立的 ORM 框架。相反,它是建立在 Java Persistence API (JPA) 规范之上的一套框架工具集[^1]。具体来说,Spring Data JPA 提供了一个高层次的抽象层,用于简化数据访问操作并减少开发者的工作量。 #### 工作原理概述 Spring Data JPA 的核心理念在于通过接口定义和方法命名约定自动生成查询逻辑,从而避免手动编写复杂的 SQL 或 JPQL 查询语句。以下是其主要工作机制: 1. **接口继承机制**: 开发者只需创建一个扩展 `JpaRepository` 接口的接口类即可获得一系列预定义的方法支持,例如 `findById`, `save`, 和 `deleteById` 等。 2. **动态查询解析**: 当调用带有特定名称模式的方法时(如 `findByLastName(String lastName)`),Spring Data JPA 能够自动将其转换为对应的 JPQL 查询[^4]。 3. **集成底层 ORM 实现**: 尽管 Spring Data JPA 不直接处理实体到表之间的映射细节,但它依赖像 Hibernate 这样的实际 ORM 框架来完成这些任务[^3]。因此,在运行时,所有的持久化操作最终都会委托给所配置的具体 JPA 提供商(通常是 Hibernate)去执行。 4. **事务管理自动化**: 基于 Spring 的声明式事务特性,任何由 Spring Data JPA 执行的操作都可以被无缝纳入到现有的事务边界内。 综上所述,虽然 Spring Data JPA 并不是一个纯粹意义上的 ORM 框架,但由于它紧密依托于 JPA 标准并与主流 ORM 解决方案相结合,所以可以认为它是构建现代企业级应用程序中不可或缺的一部分——即利用 ORM 技术实现了高效的数据库交互能力。 ```java // 示例代码展示如何简单地使用 Spring Data JPA 来查找用户记录 public interface UserRepository extends JpaRepository<User, Long> { List<User> findByLastName(String lastName); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不努力谁会可怜你?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值