使用springboot+jpa之踩坑指南

一、前言

为开发一个简单(增删改查)的请假模块,遇到项目运行不了!!!

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'leaveServiceImpl': Unsatisfied dependency expressed through field 'leaveRepository';nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'leaveRepository' defined in com.example.repair.repository.LeaveRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.example.repair.entity.Leave com.example.repair.repository.LeaveRepository.updateLeave(com.example.repair.entity.Leave)! No property updateLeave found for type Leave!

二、解决措施

话不多讲,直接上车

1.必要的注解

1.1 serviceImpl 加入@Service和@Autowired

//代码有点菜 请各位看官见谅
package com.example.repair.service.impl;

import com.example.repair.entity.Leave;
import com.example.repair.entity.Manager;
import com.example.repair.repository.LeaveRepository;
import com.example.repair.repository.ManagerRepository;
import com.example.repair.service.LeaveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * @author LouisBrilliant
 * @version 1.0
 */
@SuppressWarnings("all")
@Service
@Transactional//防止 代码执行出现错误的时候可以进行事务的回滚操作
public class LeaveServiceImpl implements LeaveService {
    @Autowired
    LeaveRepository leaveRepository;
    @Autowired
    ManagerRepository managerRepository;
    @Override
    public Leave findByLeaveId(Integer leaveId) {
        if(leaveId.intValue() >0){
            Leave leave = leaveRepository.getOne(leaveId);
            return leave;
        }
        else {
            return null;
        }
    }

    @Override
    public Boolean deleteLeave(Integer leaveId) throws Exception {
        Leave leave = leaveRepository.getOne(leaveId);
        if(leave==null){
            throw new Exception("此假条不存在");
        }else{
           leaveRepository.delete(leave);
           return true;
        }
    }

    @Override
    public Leave addLeave(Leave leave) {
        return leaveRepository.save(leave);
    }

    @Override
    public Leave findByLeaveTime(Date date) throws Exception {
        Leave byLeaveTime = leaveRepository.findByLeaveTime(date);
        if(byLeaveTime==null){
            throw new Exception("此假条不存在");
        }else{
            return byLeaveTime;//返回订单
        }

    }

    @Override
    public Leave updateLeave(Leave leave) throws Exception {

        return leaveRepository.save(leave);
    }
}

1.2 项目启动类Application

@SpringBootApplication
@Configuration
//@EntityScan(value = {"com.example.repair"})
//@EnableJpaRepositories(basePackages = "com.example.repair.repository")
//@ComponentScan(value = {"com.example.repair.controller","com.example.repair.service","com.example.repair.repository"})
public class RepairApplication {

    public static void main(String[] args) {
        SpringApplication.run (RepairApplication.class, args);
    }

}

上面三行注释掉 大家可以试一试添加 因为报错是因为没有把bean扫描到并将其注入到spring当中管理,进而引发Controller层 Service层等一系列问题 不过我的问题并不是因为没扫描的到问题(后面会讲)

关于这类措施更详细的在这篇博客 关于启动项需要的一些注解和properties文件关于jpa的配置

spring data jpa 出现Not a managed type_病毒先生的博客-CSDN博客_not a managed type

1.3 实体类的注解@Entity

查看一下实体类是否有注解@Entity

package com.example.repair.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.Date;
import java.util.Objects;

/**
 * @author LouisBrilliant
 * @version 1.0
 */
@Data //简化实体类开发
@Entity //将对象生成表格 @Entity(name="") 不给name赋值 自动默认将class名作为表名
@Table(name = "t_leave")//自己自定义表格名 如若不用次注解 则默认表名为该对象名 此注解非必须 优先级大于@Entity
public class Leave {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer leaveId;//请假Id号

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="manager_id")

    private Manager manager;
    @Temporal(TemporalType.DATE)//jpa中关于时间的注解
    @Column(columnDefinition = "date default '2021-01-01'",nullable = false)//列 默认时间2021-01-01
    private Date leaveTime;//请假日期

    private String reason;//请假理由


    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Leave leave = (Leave) o;
        return Objects.equals(leaveId, leave.leaveId) && Objects.equals(manager, leave.manager) && Objects.equals(leaveTime, leave.leaveTime) && Objects.equals(reason, leave.reason);
    }

    @Override
    public int hashCode() {
        return Objects.hash(leaveId, manager, leaveTime, reason);
    }

    @Override
    public String toString() {
        return "Leave{" +
                "leaveId=" + leaveId +
                ", manager=" + manager +
                ", leaveTime=" + leaveTime +
                ", reason='" + reason + '\'' +
                '}';
    }
}

总的来说 看看自己的Controller Service 和Dao有无做好相关的映射 好让spring识别到

相关博客

SpringBoot 整合JPA 出现 Error creating bean with name ‘userRepository’:Not a managed type 问题分析和解决方案_潇潇方远的博客-CSDN博客

2.jpa规定方法的命名规则

这就是我出错的原因 未根据jpa规定的方法命名规则书写!!!

规则 :findBy+实体类属性

//实体类Entity Leave
package com.example.repair.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.Date;
import java.util.Objects;

/**
 * @author LouisBrilliant
 * @version 1.0
 */
@Data
@Entity //将对象生成表格 @Entity(name="") 不给name赋值 自动默认将class名作为表名
@Table(name = "t_leave")//自己自定义表格名 如若不用次注解 则默认表名为该对象名 此注解非必须 优先级大于@Entity
public class Leave {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer leaveId;//请假Id号

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="manager_id")

    private Manager manager;
    @Temporal(TemporalType.DATE)//jpa中关于时间的注解
    @Column(columnDefinition = "date default '2021-01-01'",nullable = false)//列 默认时间2021-01-01
    private Date leaveTime;//请假日期
    private String reason;//请假理由
}

修改前

public interface LeaveRepository  extends JpaRepository<Leave,Integer> {
    Leave findByLeaveId(String leaveId);
    Leave findByLeaveTime(Date date);
    Leave findByLeaveManager(Manager manager);//在entity实体Leave属性中Manager才是 而不是LeaveManager!
}

修改后

public interface LeaveRepository  extends JpaRepository<Leave,Integer> {
    Leave findByLeaveId(String leaveId);
    Leave findByLeaveTime(Date date);
    Leave findByManager(Manager manager);
}

好好温习jpa方法命名规则吧~

JPA 根据解析方法名自定义查询方法(逻辑判断、相等判断、范围判断、非空判断、模糊匹配、in判断、布尔值判断、排序)_旭东怪的博客-CSDN博客_jpa 数字模糊匹配