为啥 SQL SELECT 语句在 Java Spring boot 项目中不返回 COUNT() 结果?

Posted

技术标签:

【中文标题】为啥 SQL SELECT 语句在 Java Spring boot 项目中不返回 COUNT() 结果?【英文标题】:Why a SQL SELECT statement doesn't return COUNT() result on Java Spring boot project?为什么 SQL SELECT 语句在 Java Spring boot 项目中不返回 COUNT() 结果? 【发布时间】:2021-12-29 23:28:31 【问题描述】:

这是我在这里的第一个问题,如果您需要更多信息,请询问。我正在做一个个人项目。我有一个相对复杂的关系数据库结构。我在我的 Spring Boot 项目上创建了 schema.sql 以及带有示例数据的 data.sql。我尝试为模拟健身中心网页创建一个网络应用程序。我尝试为用户显示位置名称和访问次数。我创建了一个 userLocation bean,用于将结果集保存为选择查询的列表。我可以测试关于 H2 数据库的语句及其工作。但是,在我的代码中,我无法从 select 语句中获取访问次数。

这是我的用户位置 bean,

@Data
@NoArgsConstructor
public class UserLocation 
    
    private String locName;
    private int numOfVisit;


控制器类getMapping方法

    @GetMapping("/secure/userLocation")
    public String myLocation(Model model, Authentication authentication) 
        
        String email = authentication.getName();
        User currentUser = da.findUserAccount(email);
        model.addAttribute("myLocationList", da.getUserLocationList(currentUser.getUserId()));
        
        return "/secure/userLocation";
    

这里是数据库访问方式;

public List<UserLocation> getUserLocationList(Long userId) 
        MapSqlParameterSource namedParameters = new MapSqlParameterSource();

        String query = "SELECT l.locName, COUNT(ul.dayOfVisit) FROM location l "
                + "INNER JOIN userLocation ul ON l.locId = ul.locId "
                + "INNER JOIN sec_user sc ON ul.userId = sc.userId "
                + "WHERE sc.userId = :userId AND ul.locId = 1"
                + "GROUP BY l.locName";

        namedParameters.addValue("userId", userId);
        
        return jdbc.query(query, namedParameters, new BeanPropertyRowMapper<UserLocation>(UserLocation.class));

    

这里是 schema.sql

CREATE TABLE location (
  locId         BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  locName       VARCHAR(75),
  locAddress    VARCHAR(255),
  locPhone      VARCHAR(25),
  locEmail      VARCHAR(75)
);

CREATE TABLE sec_user (
  userId            BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name              VARCHAR(75),
  lastName          VARCHAR(75),
  adress            VARCHAR(255),
  phone             VARCHAR(10),
  email             VARCHAR(75) NOT NULL UNIQUE,
  encryptedPassword VARCHAR(128) NOT NULL,
  enabled           BIT NOT NULL
);

CREATE TABLE coach (

    coachId     BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    coachName   VARCHAR(75),
    coachLevel  BIGINT,
    coachRating BIGINT,
    aboutMe     VARCHAR(255)
);

CREATE TABLE fitnessClass (

    classId     BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    className   VARCHAR(75),
    classPrice  DOUBLE
);

CREATE TABLE generalCert (
    
    certId      BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    certName    VARCHAR(75)
);

CREATE TABLE certCoach (
    
    certId      BIGINT NOT NULL,
    coachId     BIGINT NOT NULL
);

ALTER TABLE certCoach
  ADD CONSTRAINT certCoach_FK1 FOREIGN KEY (certId)
  REFERENCES generalCert (certId);

ALTER TABLE certCoach
  ADD CONSTRAINT certCoach_FK2 FOREIGN KEY (coachId)
  REFERENCES coach (coachId);

CREATE TABLE userLocation (
    
    userLocId   BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    locId       BIGINT NOT NULL,
    userId      BIGINT NOT NULL,
    isHomeLoc   BIT,
    dayOfVisit  DATE
);

ALTER TABLE userLocation
  ADD CONSTRAINT userLocation_FK1 FOREIGN KEY (locId)
  REFERENCES location (locId);

ALTER TABLE userLocation
  ADD CONSTRAINT userLocation_FK2 FOREIGN KEY (userId)
  REFERENCES sec_user (userId);  

CREATE TABLE amenity (
    amenityId   BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    amenityName VARCHAR(75),
    locId       BIGINT
);

ALTER TABLE amenity
  ADD CONSTRAINT amenity_FK FOREIGN KEY (locId)
  REFERENCES location (locId);
  
CREATE TABLE room (
    roomId      BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    roomName    VARCHAR(75),
    locId       BIGINT
);

ALTER TABLE room
  ADD CONSTRAINT room_FK FOREIGN KEY (locId)
  REFERENCES location (locId);

CREATE TABLE classCoach (
    classId  BIGINT NOT NULL,
    coachId  BIGINT NOT NULL
);

ALTER TABLE classCoach
  ADD CONSTRAINT classCoachFK1   FOREIGN KEY (classId)
    REFERENCES fitnessClass(classId);

ALTER TABLE classCoach
  ADD CONSTRAINT classCoachFK2    FOREIGN KEY (coachId)
    REFERENCES coach(coachId);

CREATE TABLE schedule (
    ScheduleId      BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    ScheduleDate    DATE,
    ScheduleTime    TIME,
    RoomId          BIGINT,
    ClassId         BIGINT NOT NULL,
    LocId           BIGINT NOT NULL
);
    
ALTER TABLE schedule
  ADD CONSTRAINT scheduleFK1  FOREIGN KEY (roomId)
    REFERENCES room(RoomId);
    
ALTER TABLE schedule
  ADD CONSTRAINT scheduleFK2  FOREIGN KEY (classId)
    REFERENCES fitnessClass(classId);
    
ALTER TABLE schedule
  ADD CONSTRAINT ScheduleFK3  FOREIGN KEY (LocId)
    REFERENCES location(LocId);

CREATE TABLE reservation (
    ClassId     BIGINT NOT NULL,
    userId      BIGINT NOT NULL
);

ALTER TABLE reservation
  ADD CONSTRAINT reservationFK1  FOREIGN KEY (classId)
    REFERENCES fitnessClass(classId);
    
ALTER TABLE reservation
  ADD CONSTRAINT reservationFK2  FOREIGN KEY (userId)
    REFERENCES sec_user(userId);

CREATE TABLE workFrom (
    coachId     BIGINT NOT NULL,
    locId       BIGINT NOT NULL
);

ALTER TABLE workFrom
  ADD CONSTRAINT workFromFK1  FOREIGN KEY (coachId)
    REFERENCES coach(coachId);
    
ALTER TABLE workFrom
  ADD CONSTRAINT workFromFK2  FOREIGN KEY (locId)
    REFERENCES location(locId);

CREATE TABLE review (
    ReviewId    BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    CoachId     BIGINT NOT NULL,
    userId    BIGINT NOT NULL,
    ReviewDate  DATE,
    ComScore    CHAR(1),
    EnthScore   CHAR(1),
    PunctScore  CHAR(1),
    ReviewText  VARCHAR(500)
);

ALTER TABLE review
  ADD CONSTRAINT reviewFK1  FOREIGN KEY (coachId)
    REFERENCES coach(coachId);
ALTER TABLE review
  ADD CONSTRAINT reviewFK2  FOREIGN KEY (userId)
    REFERENCES sec_user(userId);

CREATE TABLE Reference (
    CoachId     BIGINT NOT NULL,
    userId    BIGINT NOT NULL
);
ALTER TABLE Reference
  ADD CONSTRAINT ReferenceFK1  FOREIGN KEY (coachId)
    REFERENCES coach(coachId);
ALTER TABLE review
  ADD CONSTRAINT ReferenceFK2  FOREIGN KEY (userId)
    REFERENCES sec_user(userId);

CREATE TABLE ClientCoach (
    coachId     BIGINT NOT NULL,
    userId    BIGINT NOT NULL,
    myCoach     BIT
);

ALTER TABLE ClientCoach
  ADD CONSTRAINT ClientCoachFK1  FOREIGN KEY (coachId)
    REFERENCES coach(coachId);
ALTER TABLE ClientCoach
  ADD CONSTRAINT ClientCoachFK2  FOREIGN KEY (userId)
    REFERENCES sec_user(userId);


CREATE TABLE sec_role(
  roleId   BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  roleName VARCHAR(30) NOT NULL UNIQUE
);

CREATE TABLE user_role
(
  id     BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  userId BIGINT NOT NULL,
  roleId BIGINT NOT NULL
);


ALTER TABLE user_role
  ADD CONSTRAINT user_role_uk UNIQUE (userId, roleId);

ALTER TABLE user_role
  ADD CONSTRAINT user_role_fk1 FOREIGN KEY (userId)
  REFERENCES sec_user (userId);
 
ALTER TABLE user_role
  ADD CONSTRAINT user_role_fk2 FOREIGN KEY (roleId)
  REFERENCES sec_role (roleId);

Here the result web page

Here is EERD for the schema

【问题讨论】:

映射器如何确定COUNT(ul.dayOfVisit) 映射到numOfVisit?查看 Javadoc:docs.spring.io/spring-framework/docs/current/javadoc-api/org/… 谢谢。我会对此进行审查。 【参考方案1】:

请尝试:

SELECT l.locName, COUNT(ul.dayOfVisit) AS numOfVisit -- ...

(别名 numOfVisit),因为我们使用的是 BeanPropertyRowMapper(通过“bean 属性”(即“字段名称”)映射:https://www.google.com/search?q=java+bean+naming+conventions)。

或者使用其他/自定义RowMapper

因为即使是 javadoc 也推荐:

... 为获得最佳性能,请考虑使用自定义 RowMapper 实现。

最佳:

return jdbc.query(query, namedParameters, 
  (ResultSet rs, int rowNum) ->  // one ResultSet per row:
      // column indices start with 1(!):
      return new UserLocation(rs.getString(1), rs.getInt(2));
      // alternatively (name based): rs.getString("locName")...
    
);

;)


RowMapper javadoc (spring-jdbc:current) ResultSet javadoc (jdk17) 由于RowMapper 是/满足functional interface 的要求,我们可以将其写为lambda expression。

【讨论】:

请看更新:使用自定义! 我会的。再次感谢。我有很多东西要学:)我希望我能问更多的难题,但这很容易。对此感到抱歉。

以上是关于为啥 SQL SELECT 语句在 Java Spring boot 项目中不返回 COUNT() 结果?的主要内容,如果未能解决你的问题,请参考以下文章

在 SELECT 语句中使用自定义函数时,为啥我的 SQL 查询的输出显示不正确?

MySQL中为啥不能在select语句中使用into将查询结果存入新表,但是SQL sever可以

Oracle中,为啥同样的SELECT查询语句,加了CREATE TABLE AS后速度更快了?

mybatis为啥执行select语句是,返回的结果都是空的

在Oracle中定义SQL查询。索引为啥不能直接从select语句中引用?求教,谢谢

T-SQL语句中使用select…………union 插入数据是为啥不能使用DEFAULT