spring data jpa 入门看这一篇文章就够了

spring data jpa 入门看这一篇文章就够了

目录

项目构建

快速入门实操

扩展使用

扩展使用二:自定义sql @Query


项目构建

  • 新建项目,引入maven坐标
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.22</version>
        </dependency>

    </dependencies>
  • 数据库表sql
CREATE TABLE `goods`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `good_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '商品名称',
  `good_price` decimal(10, 2) NOT NULL COMMENT '商品单价',
  `add_time` timestamp(0) NOT NULL COMMENT '添加时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
  • 搭建springboot项目,由于项目比较简单,就不再演示.展示目录结构。抛开所有的杂七杂八的,我们只看我们想要的,直接明了。 但是需要在我们的启动类,也就是DemoApplication上增加扫描注解 
    @ComponentScan(basePackages = {"com.zhw.jpademo.demo.dao"}) 扫描dao包下所有的Repository
  •  
  • 标题

     

  • 配置项目application.yml
server:
  port: 8081
  tomcat:
    max-http-header-size: 8192

spring:
  #mysql config 配置数据库连接
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/shop_goods
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

  jpa:
    #在控制台打印sql
    show-sql: true
    hibernate:
#ddl-auto:create----每次运行该程序,没有表格会新建表格,表内有数据会清空
#ddl-auto:create-drop----每次程序结束的时候会清空表
#ddl-auto:update----每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
#ddl-auto:validate----运行程序会校验数据与数据库的字段类型是否相同,不同会报错
      ddl-auto: update

快速入门实操

  • Goods实体类,这个实体类很关键,@Table注解用来标识实体类与数据表的对应关系,@Column注解来标识实体类中属性与数据表中字段的对应关系
@Data
@Entity
@Table(name = "goods")
public class Goods {

    @Id    //主键id
    @GeneratedValue(strategy= GenerationType.IDENTITY)//主键生成策略
    @Column(name="id")//数据库字段名
    private Integer id;

    @Column(name = "good_name")
    private String goodName;

    @Column(name = "good_price")
    private BigDecimal goodPrice;

    @Column(name = "add_time")
    private Timestamp addTime;
}
  • 定义完实体类后,我们开始编写我们的持久层,也就是 GoodsRepository,使用jpa很简单,只需要继承一下 JpaRepository<T, ID>。不需要在添加任何注解
  • 其中T表示要 实体类名,ID表示主键类型。代码如下
    public interface GoodsRepository extends JpaRepository<Goods,Integer> {
    }

     

  • 接下来我们直接在Controller中操作一下试试手。

@RestController
@SpringBootApplication
@ComponentScan(basePackages = {"com.zhw.jpademo.demo.dao"})
public class DemoApplication {

    // 我们注入GoodsRepository 
    @Autowired
    private GoodsRepository goodsRepository;

    @RequestMapping(value = "/")
    public String home() {
        // findAll 查找表下所有的数据,具体代码可以查看JpaRepository接口中提供的方法
        List<Goods> all = goodsRepository.findAll();
        System.out.println(all);
}

扩展使用

  • 当然除了JpaRepository中提供的方法,我们还可以有额外的使用,例如当我们查询名称为 商品3的数据时,我们可以这样写。findByGoodName。只要按照驼峰命名,jpa关键字去编写,jpa就能识别成功!
Goods goods1 = goodsRepository.findByGoodName("商品3");
System.out.println(goods1);
  • 那么有些同学要问了,如果我想使用sql,该怎么操作呢?看 扩展使用二 把。

扩展使用二:自定义sql @Query

注意注意:注解中写的是HQL,所以查询的是对象,而不是表名,我们的对象是Goods  而不是数据库中的goods表,查询的字段也是对象的成员,不是表的字段。(好多文章没有提及这个,导致很多程序运行报错)

    /**
     * 自定义sql查询脚本
     * 注解中写的是HQL,所以查询的是对象,而不是表名
     * 同样的问题,查询的字段也是对象的成员,不是表的字段
     * @param name
     * @return
     */
    @Query(" SELECT g FROM Goods g WHERE goodName LIKE concat('%', :name, '%') ")
    List<Goods> myGoods(@Param("name") String name);
  • 我们先在用2种方法增加一条数据。值得一提的是
    • Spring Data 提供 了默认的事务处理方式,即 所有的查询均声明为只读 事务 。

    • 对于自定义的方法,如需 改变 S pringData 提供 的事务默认方式,可以在方法上 注解 @Transactional 声明

    • 在Controller,或者Service 上使用  @Transactional。我的demo中就直接在Controller上加了

  • 第一种,使用JpaRepository中的save方法。有趣的是,save方法不仅是新增,还是更新,当我表中的数据(主键)存在时,便会更新这条数据。可以试试哦。测试代码如下:
            // 因为主键策略是自动新增,从1开始,那么这段代码执行成功后,数据库中会多出一条id=1的数据
            Goods goods = new Goods();
            goods.setAddTime(new Timestamp(System.currentTimeMillis()));
            goods.setGoodName("商品2");
            goods.setGoodPrice(new BigDecimal(0.01));
            goodsRepository.save(goods);
            
            // 然后我们使用save去更新这条数据,设置id为1
            Goods goods2 = new Goods();
            goods2.setId(1);
            goods2.setAddTime(new Timestamp(System.currentTimeMillis()));
            goods2.setGoodName("商品3");
            goods.setGoodPrice(new BigDecimal(0.01));
            goodsRepository.save(goods2);
  • 第二种,使用@query方法去保存,我们编写 GoodsRepository
  • 在@Query注解中编写JPQL实现 DELETE 和 UPDATE 操作的时候必须加上@modifying注解
    /**
     * 自定义sql 插入脚本
     * @param goods
     * @return
     */
    @Modifying
    @Query(value = " INSERT INTO  goods (good_name, good_price, add_time) VALUES (:#{#igoods.goodName},:#{#igoods.goodPrice},:#{#igoods.addTime} ) ",nativeQuery = true)
    int addNewGoods(@Param("igoods") Goods goods);
  • 发现什么不一样了吗?我们在 【查询】操作的时,查询的是对象不是表名。但是在【插入】操作时候则直接写的是insert into goods 是数据库的表,而不是Goods对象。属性也是同样的到了.
  • 这一切都是 【nativeQuery】的作用,当为 true 时是可以执行原生sql语句,所谓原生sql,也就是说这段sql拷贝到数据库中。
  • 就不是原生sql,而其中的 select * from xxx中xxx也不是数据库对应的真正的表名,而是对应的实体名,并且sql中的字段名也不是数据库中真正的字段名,而是实体的字段名

 

  • 值的一提的是,如果你们执行代码抛出异常如下。则说明你们在更新操作时候没有加 @Transactional .

    javax.persistence.TransactionRequiredException: Executing an update/delete query
    	at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
    	at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1668) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
    	at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:239) ~[spring-data-jpa-2.4.3.jar:2.4.3]
    	at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88) ~[spring-data-jpa-2.4.3.jar:2.4.3]
    	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155) ~[spring-data-jpa-2.4.3.jar:2.4.3]

    emmm,目前就写完了,哈哈哈哈。所有的源码如下
    Controller:

    
    @RestController
    @SpringBootApplication
    @ComponentScan(basePackages = {"com.zhw.jpademo.demo.dao"})
    public class DemoApplication {
    
        @Autowired
        private GoodsRepository goodsRepository;
    
        @RequestMapping(value = "/")
        @Transactional
        public String home() {
    //        List<Goods> all = goodsRepository.findAll();
    //        System.out.println(all);
    //
    //        Goods goods = new Goods();
    //        goods.setAddTime(new Timestamp(System.currentTimeMillis()));
    //        goods.setGoodName("商品2");
    //        goods.setGoodPrice("0.01");
    //        goodsRepository.save(goods);
    //
    //        Goods goods2 = new Goods();
    //        goods2.setId(5);
    //        goods2.setAddTime(new Timestamp(System.currentTimeMillis()));
    //        goods2.setGoodName("商品3");
    //        goods2.setGoodPrice("0.03");
    //        goodsRepository.save(goods2);
    
            //Goods goods1 = goodsRepository.findByGoodName("商品3");
            //System.out.println(goods1);
    
            List<Goods> allGoods = goodsRepository.findAllByGoodName("商品2");
            System.out.println(allGoods);
    
            List<Goods> findGoods = goodsRepository.myGoods("3");
            System.out.println(findGoods);
    
    //        goods1.setGoodName("新商品");
    //        int update = goodsRepository.updateGoods(goods1);
    //        System.out.println(update);
    
    
            Goods newGoods = new Goods();
            newGoods.setGoodName("新增商品");
            newGoods.setAddTime(new Timestamp(System.currentTimeMillis()));
            newGoods.setGoodPrice(new BigDecimal(20.12));
            goodsRepository.addNewGoods(newGoods);
            return "服务启动成功";
        }
    
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
    }
    
    GoodsRepository
    
    
    
    /**
     * @author ZhangHaiWen
     * @title: GoodsRepository
     * @projectName minipasscheck
     * @description: 商户response
     * @date 2021/2/1415:44
     */
    public interface GoodsRepository extends JpaRepository<Goods,Integer> {
    
        @Override
        List<Goods> findAll();
    
        /**
         * 根据商品名称查询商品
         * @param name
         * @return
         */
        Goods findByGoodName(String name);
    
        /**
         * 根据商品名称查询所有商品
         * @param name
         * @return
         */
        List<Goods> findAllByGoodName(String name);
    
        /**
         * 自定义sql查询脚本
         * 注解中写的是HQL,所以查询的是对象,而不是表名
         * 同样的问题,查询的字段也是对象的成员,不是表的字段
         * @param name
         * @return
         */
        @Query(" SELECT g FROM Goods g WHERE goodName LIKE concat('%', :name, '%') ")
        List<Goods> myGoods(@Param("name") String name);
    
        /**
         * 自定义sql 插入脚本
         * @param goods
         * @return
         */
        @Modifying
        @Query(value = " INSERT INTO  goods (good_name, good_price, add_time) VALUES (:#{#igoods.goodName},:#{#igoods.goodPrice},:#{#igoods.addTime} ) ",nativeQuery = true)
        int addNewGoods(@Param("igoods") Goods goods);
    
        /**
         * 自定义sql 更新操作
         * @param goods
         * @return
         */
        @Modifying
        @Query(value = "update goods set good_name = :#{#igoods.goodName} where id = :#{#igoods.id}",nativeQuery = true)
        int updateGoods(@Param("igoods") Goods goods);
    
    
        /**
         * 自定义sql 更新操作
         * @param goods
         * @return
         */
        @Modifying
        @Query(value = "update Goods set goodName = :#{#igoods.goodName} where id = :#{#igoods.id}")
        int updateGoodsNonativeQuery(@Param("igoods") Goods goods);
    
    }
    

     

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值