Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.TwoSeaU.BaData.domain.trade.controller;

import com.TwoSeaU.BaData.domain.trade.service.PostService;
import com.TwoSeaU.BaData.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/trades")
public class MockController {
private final PostService postService;

@PostMapping("/mock/posts")
public ResponseEntity<ApiResponse<String>> createMockPost() {
return ResponseEntity.ok().body(ApiResponse.success(postService.generateGifticons()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPosts(
return ResponseEntity.ok().body(ApiResponse.success(postSearchService.searchPosts(query, user == null ? null : user.getUsername(), cursor, size)));
}

@GetMapping("/posts/rdb")
public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPostsByRDB(
@RequestParam(required = false) Long cursor,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String query,
@AuthenticationPrincipal User user) {
return ResponseEntity.ok().body(ApiResponse.success(postSearchService.searchPostsByRDB(query, user == null ? null : user.getUsername(), cursor, size)));
}

@GetMapping("/posts/{userId}/{isSold}")
public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPostsByUserId(
@RequestParam(required = false) Long cursor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import com.TwoSeaU.BaData.domain.trade.dto.response.PostsResponse;
import com.TwoSeaU.BaData.domain.trade.dto.response.SaveRecommendLikesResponse;
import com.TwoSeaU.BaData.domain.trade.service.LikeService;
import com.TwoSeaU.BaData.domain.trade.service.RecommendService;
import com.TwoSeaU.BaData.domain.trade.service.recommend.GlobalRecommendService;
import com.TwoSeaU.BaData.domain.trade.service.recommend.doubleVector.RecommendServiceDouble;
import com.TwoSeaU.BaData.domain.trade.service.recommend.floatVector.RecommendServiceFloat;
import com.TwoSeaU.BaData.domain.trade.service.recommend.pgVector.RecommendServicePg;
import com.TwoSeaU.BaData.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand All @@ -15,16 +18,40 @@
@RequiredArgsConstructor
@RequestMapping("/api/v1/trades/posts/recommend")
public class RecommendController {
private final RecommendService recommendService;
private final RecommendServiceDouble doubleRecommendServiceDouble;
private final RecommendServiceFloat floatRecommendServiceFloat;
private final RecommendServicePg pgvectorRecommendServicePg;
private final GlobalRecommendService globalRecommendService;
Comment on lines +21 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

필드명과 타입 불일치

필드명에 타입 정보가 중복되어 있어 가독성이 떨어집니다.

-private final RecommendServiceDouble doubleRecommendServiceDouble;
-private final RecommendServiceFloat floatRecommendServiceFloat;
-private final RecommendServicePg pgvectorRecommendServicePg;
+private final RecommendServiceDouble recommendServiceDouble;
+private final RecommendServiceFloat recommendServiceFloat;
+private final RecommendServicePg recommendServicePg;

이에 따라 메서드 호출부도 수정해야 합니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private final RecommendServiceDouble doubleRecommendServiceDouble;
private final RecommendServiceFloat floatRecommendServiceFloat;
private final RecommendServicePg pgvectorRecommendServicePg;
private final GlobalRecommendService globalRecommendService;
private final RecommendServiceDouble recommendServiceDouble;
private final RecommendServiceFloat recommendServiceFloat;
private final RecommendServicePg recommendServicePg;
private final GlobalRecommendService globalRecommendService;
🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
around lines 21 to 24, the field names redundantly include type information,
reducing readability. Rename the fields to remove type details so that names
clearly represent their purpose without duplicating type info. After renaming,
update all method calls and references to these fields accordingly to match the
new names.

private final LikeService likeService;

@GetMapping("/double")
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByDouble(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(doubleRecommendServiceDouble.recommendPosts(user == null ? null : user.getUsername(), isStart)));
}

@GetMapping("/float")
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByFloat(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(floatRecommendServiceFloat.recommendPostsByFloat(user == null ? null : user.getUsername(), isStart)));
}

//@GetMapping("/pgvector")
@GetMapping
public ResponseEntity<ApiResponse<PostsResponse>> recommendPosts(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(recommendService.recommendPosts(user == null ? null : user.getUsername(), isStart)));
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByPgvector(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(pgvectorRecommendServicePg.recommendPostsBypgVector(user == null ? null : user.getUsername(), isStart)));
}

@PostMapping("/likes/{postId}")
public ResponseEntity<ApiResponse<SaveRecommendLikesResponse>> likeRecommendation(@AuthenticationPrincipal User user, @PathVariable Long postId) {
return ResponseEntity.ok().body(ApiResponse.success(likeService.likesAtRecommendation(user == null ? null : user.getUsername(), postId)));
}

@PatchMapping("/vector/update/all/double")
public ResponseEntity<ApiResponse<String>> updateAllPostForDouble() {
return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllDoubleVector()));
}

@PatchMapping("/vector/update/all/float")
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

메서드명과 기능 불일치

updateAllPostVectorForPgvector 메서드명이 실제로는 float와 pgVector를 모두 업데이트하는 기능과 일치하지 않습니다.

-public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
+public ResponseEntity<ApiResponse<String>> updateAllPostVectorForFloatAndPg() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForFloatAndPg() {
🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
at line 54, the method name updateAllPostVectorForPgvector does not accurately
reflect its functionality, which updates both float and pgVector values. Rename
the method to a name that clearly indicates it updates all post vectors
including both float and pgVector types to improve code clarity and
maintainability.

return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllFloatAndPgVector()));
}
Comment on lines +48 to +56
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

벌크 벡터 업데이트 엔드포인트 보안 우려

벌크 벡터 업데이트 엔드포인트들이 인증 없이 노출되어 있어 보안상 위험할 수 있습니다.

관리자 권한 검증을 추가해주세요:

@PatchMapping("/vector/update/all/double")
-public ResponseEntity<ApiResponse<String>> updateAllPostForDouble() {
+public ResponseEntity<ApiResponse<String>> updateAllPostForDouble(@AuthenticationPrincipal User user) {
+    // 관리자 권한 검증 로직 추가
    return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllDoubleVector()));
}

또는 별도의 관리자 컨트롤러로 분리하는 것을 고려해주세요.

🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
around lines 48 to 56, the bulk vector update endpoints lack authentication and
authorization checks, posing a security risk. Add an authorization check to
ensure only users with admin privileges can access these endpoints, such as
using a security annotation like @PreAuthorize("hasRole('ADMIN')") or
equivalent. Alternatively, move these endpoints to a separate controller
dedicated to admin operations and secure that controller accordingly.

}
17 changes: 12 additions & 5 deletions src/main/java/com/TwoSeaU/BaData/domain/trade/entity/Gifticon.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public class Gifticon extends Post{
@Column(nullable = false)
private String partner;

private double[] vector;
private double[] doubleVector;

private float[] floatVector;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id", nullable = false)
Expand All @@ -34,16 +36,21 @@ public class Gifticon extends Post{
public Gifticon(final User user, final String title, final String comment, final BigDecimal price,
final LocalDate deadLine, final String postImage, final Boolean isSold,
final String couponNumber, final String partner, final GifticonCategory category,
final double[] vector) {
final double[] doubleVector, final float[] floatVector) {
super(user, title, comment, price, deadLine, postImage, isSold);
this.couponNumber = couponNumber;
this.partner = partner;
this.category = category;
this.vector = vector;
this.doubleVector = doubleVector;
this.floatVector = floatVector;
}

public void updateDoubleVector(final double[] doubleVector) {
this.doubleVector = doubleVector;
}

public void updateVector(final double[] vector) {
this.vector = vector;
public void updateFloatVector(final float[] floatVector) {
this.floatVector = floatVector;
}
Comment on lines +48 to 54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

벡터 차원 검증 필요

벡터 업데이트 시 예상 차원과 일치하는지 검증이 없습니다. 잘못된 차원의 벡터가 저장되면 추천 시스템에서 오류가 발생할 수 있습니다.

     public void updateDoubleVector(final double[] doubleVector) {
+        // 예상 벡터 차원 검증 추가
+        if (doubleVector != null && doubleVector.length != EXPECTED_VECTOR_SIZE) {
+            throw new IllegalArgumentException("Invalid vector dimension: " + doubleVector.length);
+        }
         this.doubleVector = doubleVector;
     }
 
     public void updateFloatVector(final float[] floatVector) {
+        if (floatVector != null && floatVector.length != EXPECTED_VECTOR_SIZE) {
+            throw new IllegalArgumentException("Invalid vector dimension: " + floatVector.length);
+        }
         this.floatVector = floatVector;
     }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/entity/Gifticon.java between
lines 48 and 54, the updateDoubleVector and updateFloatVector methods lack
validation for the vector dimensions. Add checks to verify that the input vector
length matches the expected dimension before assigning it to the class fields.
If the dimension does not match, throw an appropriate exception or handle the
error to prevent storing invalid vectors.


public void updateBarcodeViewTime(final LocalDateTime barcodeViewTime) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.TwoSeaU.BaData.domain.trade.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Table(name = "post_vector")
public class PostVector {
@Id
private Long id;

@Column(name = "vector_pg", columnDefinition = "vector(57)")
private float[] vectorPg;
Comment on lines +18 to +19
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

벡터 차원 수를 검증하세요.

vector(57) 차원이 하드코딩되어 있습니다. 실제 벡터화된 특성의 차원 수와 일치하는지 확인이 필요합니다.

벡터 차원을 확인하기 위해 다음 스크립트를 실행하세요:


🏁 Script executed:

#!/bin/bash
# 벡터화 서비스에서 실제 생성되는 벡터 차원 확인
ast-grep --pattern 'vectorizePost($$$) {
  $$$
  return vectorUtils.concatenate($$$);
}'

# 카테고리와 파트너 인덱스 맵의 크기 확인
rg -A 3 "categoryToIndex.*put|partnerToIndex.*put"

Length of output: 2853


🏁 Script executed:

#!/bin/bash
# 전체 PostVectorizer 클래스 내용 및 벡터화 메서드 확인
sed -n '1,200p' src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

# vectorizePost 메서드 시그니처와 내부 concatenate 호출 위치 확인
rg "vectorizePost" -A5 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java
rg "concatenate" -A5 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

# 카테고리 및 제휴사 리스트 초기화 위치 확인
rg "List<.*categories" -A3 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java
rg "List<.*partners" -A3 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

Length of output: 4581


벡터 차원 크기 검증 및 상수화 필요

PostVector 엔티티의 @Column(columnDefinition = "vector(57)")에 하드코딩된 57이 실제 벡터화 로직과 일치하는지 반드시 확인하세요.
현재 vectorizePost(...) 메서드는
• 카테고리 수 (categoryToIndex.size())
• 제휴사 수 (partnerToIndex.size())
• 수치형 특성 2개
를 합쳐 벡터를 생성하므로, 총 차원 수는 (카테고리 개수 + 제휴사 개수 + 2)가 됩니다.
이 값이 57과 동일한지 점검하고, 유지보수를 위해 별도 상수 또는 설정값으로 분리하는 것을 권장합니다.

선택 사항:

  • PostVector 생성 전용 factory 메서드를 추가해 엔티티 생성 방식을 일관성 있게 관리할 수 있습니다.

– src/main/java/com/TwoSeaU/BaData/domain/trade/entity/PostVector.java, 18–19번 라인 확인

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/entity/PostVector.java at lines
18-19, the vector dimension size is hardcoded as 57 in the @Column annotation.
Verify that this matches the actual vector size calculated as
(categoryToIndex.size() + partnerToIndex.size() + 2). To fix, replace the
hardcoded 57 with a constant or configuration value representing the vector
dimension to ensure consistency and maintainability. Optionally, add a factory
method for creating PostVector instances to centralize and standardize entity
creation.


@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.TwoSeaU.BaData.domain.trade.repository;

import com.TwoSeaU.BaData.domain.trade.entity.Gifticon;
import com.TwoSeaU.BaData.domain.trade.exception.TradeException;
import com.TwoSeaU.BaData.domain.trade.service.recommend.floatVector.RecommendServiceFloat;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

아키텍처 계층 분리 위반

Repository 계층에서 Service 계층의 클래스(RecommendServiceFloat.RecommendationResult)를 import하는 것은 계층 간 의존성을 역전시킵니다. Repository는 도메인 엔티티나 DTO만 반환해야 합니다.

별도의 DTO 클래스를 생성하여 계층 간 의존성을 해결하는 것을 권장합니다:

-import com.TwoSeaU.BaData.domain.trade.service.recommend.floatVector.RecommendServiceFloat;
+// RecommendationResult를 별도 DTO로 분리하여 domain.dto 패키지에 위치

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/repository/JdbcRepository.java
at line 5, the import of RecommendServiceFloat from the service layer violates
architecture layering by creating a dependency from repository to service. To
fix this, remove the import and create a separate DTO class in the domain or a
shared package that represents the data needed, then have the repository return
that DTO instead of the service class. This decouples the repository from the
service layer and maintains proper layering.

import com.TwoSeaU.BaData.global.response.GeneralException;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

@Repository
@RequiredArgsConstructor
public class JdbcRepository {
private final GifticonRepository gifticonRepository;
private final DataSource dataSource;
private final JdbcTemplate jdbcTemplate;
private final int LIMIT = 10;

public List<RecommendServiceFloat.RecommendationResult> findSimilarPosts(final float[] userVector, final int alreadyViewCount) {
final String sql = """
SELECT id, vector_pg <=> ?::vector AS similarity
FROM post_vector
ORDER BY vector_pg <=> ?::vector
limit ?
;
""";

try (Connection conn = dataSource.getConnection()) {
return jdbcTemplate.query(
sql,
ps -> {
ps.setObject(1, toPgvectorString(userVector));
ps.setObject(2, toPgvectorString(userVector));
ps.setInt(3, LIMIT + alreadyViewCount);
},
(rs, rowNum) -> {
Long postId = rs.getLong("id");
System.out.println("Post ID: " + postId);
Gifticon gifticon = gifticonRepository.findById(postId)
.orElseThrow(() -> new GeneralException(TradeException.POST_NOT_FOUND));

return new RecommendServiceFloat.RecommendationResult(
gifticon,
rs.getDouble("similarity"),
rs.getDouble("similarity")
);
}
);

} catch (SQLException e) {
throw new RuntimeException("추천 게시글 검색 실패", e);
}
Comment on lines +33 to +57
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

리소스 관리 및 성능 개선 필요

여러 개선 사항이 필요합니다:

  1. 불필요한 Connection 생성: JdbcTemplate이 연결을 자체 관리하므로 수동 Connection 생성이 불필요합니다.
  2. 디버그 코드 제거: 프로덕션 코드에서 System.out.println을 제거해야 합니다.
  3. N+1 쿼리 문제: 각 결과마다 개별적으로 Gifticon을 조회합니다.

다음과 같이 개선하세요:

-        try (Connection conn = dataSource.getConnection()) {
-            return jdbcTemplate.query(
-                    sql,
-                    ps -> {
-                        ps.setObject(1, toPgvectorString(userVector));
-                        ps.setObject(2, toPgvectorString(userVector));
-                        ps.setInt(3, LIMIT + alreadyViewCount);
-                    },
-                    (rs, rowNum) -> {
-                        Long postId = rs.getLong("id");
-                        System.out.println("Post ID: " + postId);
-                        Gifticon gifticon = gifticonRepository.findById(postId)
-                                .orElseThrow(() -> new GeneralException(TradeException.POST_NOT_FOUND));
+        return jdbcTemplate.query(
+                sql,
+                ps -> {
+                    String vectorString = toPgvectorString(userVector);
+                    ps.setObject(1, vectorString);
+                    ps.setObject(2, vectorString);
+                    ps.setInt(3, LIMIT + alreadyViewCount);
+                },
+                (rs, rowNum) -> {
+                    Long postId = rs.getLong("id");
+                    Gifticon gifticon = gifticonRepository.findById(postId)
+                            .orElseThrow(() -> new GeneralException(TradeException.POST_NOT_FOUND));

-                        return new RecommendServiceFloat.RecommendationResult(
-                                gifticon,
-                                rs.getDouble("similarity"),
-                                rs.getDouble("similarity")
-                        );
-                    }
-            );
-
-        } catch (SQLException e) {
-            throw new RuntimeException("추천 게시글 검색 실패", e);
-        }
+                    return new RecommendServiceFloat.RecommendationResult(
+                            gifticon,
+                            rs.getDouble("similarity"),
+                            rs.getDouble("similarity")
+                    );
+                }
+        );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try (Connection conn = dataSource.getConnection()) {
return jdbcTemplate.query(
sql,
ps -> {
ps.setObject(1, toPgvectorString(userVector));
ps.setObject(2, toPgvectorString(userVector));
ps.setInt(3, LIMIT + alreadyViewCount);
},
(rs, rowNum) -> {
Long postId = rs.getLong("id");
System.out.println("Post ID: " + postId);
Gifticon gifticon = gifticonRepository.findById(postId)
.orElseThrow(() -> new GeneralException(TradeException.POST_NOT_FOUND));
return new RecommendServiceFloat.RecommendationResult(
gifticon,
rs.getDouble("similarity"),
rs.getDouble("similarity")
);
}
);
} catch (SQLException e) {
throw new RuntimeException("추천 게시글 검색 실패", e);
}
return jdbcTemplate.query(
sql,
ps -> {
String vectorString = toPgvectorString(userVector);
ps.setObject(1, vectorString);
ps.setObject(2, vectorString);
ps.setInt(3, LIMIT + alreadyViewCount);
},
(rs, rowNum) -> {
Long postId = rs.getLong("id");
Gifticon gifticon = gifticonRepository.findById(postId)
.orElseThrow(() -> new GeneralException(TradeException.POST_NOT_FOUND));
return new RecommendServiceFloat.RecommendationResult(
gifticon,
rs.getDouble("similarity"),
rs.getDouble("similarity")
);
}
);
🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/repository/JdbcRepository.java
lines 33 to 57, remove the manual Connection acquisition since JdbcTemplate
manages connections automatically. Eliminate the System.out.println debug
statement. To fix the N+1 query issue, refactor the code to fetch all Gifticon
entities in a single query based on the collected post IDs from the result set,
then map them accordingly when creating RecommendationResult objects.

}

public void insertPostVector(final Long postId, final float[] vector) {
final String sql = "INSERT INTO post_vector (id, vector_pg) VALUES (?, ?::vector)";

try (Connection conn = dataSource.getConnection()) {
jdbcTemplate.update(sql, postId, toPgvectorString(vector));
} catch (SQLException e) {
throw new RuntimeException("Post vector insert failed", e);
}
Comment on lines +63 to +67
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

불필요한 Connection 관리

JdbcTemplate이 연결을 내부적으로 관리하므로 수동 Connection 생성이 불필요합니다.

-        try (Connection conn = dataSource.getConnection()) {
-            jdbcTemplate.update(sql, postId, toPgvectorString(vector));
-        } catch (SQLException e) {
-            throw new RuntimeException("Post vector insert failed", e);
-        }
+        jdbcTemplate.update(sql, postId, toPgvectorString(vector));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try (Connection conn = dataSource.getConnection()) {
jdbcTemplate.update(sql, postId, toPgvectorString(vector));
} catch (SQLException e) {
throw new RuntimeException("Post vector insert failed", e);
}
jdbcTemplate.update(sql, postId, toPgvectorString(vector));
🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/repository/JdbcRepository.java
around lines 63 to 67, remove the manual Connection acquisition using
dataSource.getConnection() since JdbcTemplate manages connections internally.
Refactor the code to call jdbcTemplate.update(sql, postId,
toPgvectorString(vector)) directly without wrapping it in a try-with-resources
block for Connection.

}

public void updatePostVector(final Long postId, final float[] vector) {
final String sql = "UPDATE post_vector SET vector_pg = ?::vector WHERE id = ?";

try (Connection conn = dataSource.getConnection()) {
jdbcTemplate.update(sql, toPgvectorString(vector), postId);
} catch (SQLException e) {
throw new RuntimeException("Post vector update failed", e);
}
Comment on lines +73 to +77
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Connection 관리 및 매개변수 순서 일관성

  1. JdbcTemplate이 연결을 관리하므로 수동 Connection 생성이 불필요합니다.
  2. insertPostVector와 매개변수 순서가 다릅니다 (일관성 부족).
-        try (Connection conn = dataSource.getConnection()) {
-            jdbcTemplate.update(sql, toPgvectorString(vector), postId);
-        } catch (SQLException e) {
-            throw new RuntimeException("Post vector update failed", e);
-        }
+        jdbcTemplate.update(sql, toPgvectorString(vector), postId);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try (Connection conn = dataSource.getConnection()) {
jdbcTemplate.update(sql, toPgvectorString(vector), postId);
} catch (SQLException e) {
throw new RuntimeException("Post vector update failed", e);
}
jdbcTemplate.update(sql, toPgvectorString(vector), postId);
🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/repository/JdbcRepository.java
around lines 73 to 77, remove the manual Connection creation since JdbcTemplate
manages connections automatically. Also, ensure the parameter order in
jdbcTemplate.update matches the order used in insertPostVector for consistency.
Adjust the method call accordingly to fix both issues.

}


private String toPgvectorString(float[] vector) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < vector.length; i++) {
sb.append(vector[i]);
if (i < vector.length - 1) sb.append(", ");
}
sb.append("]");

return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public CursorPageResponse<PostResponse> searchPosts(final String query, final St
return searchByTitleAndComment(query, username, cursor, size);
}

public CursorPageResponse<PostResponse> searchPostsByRDB(final String query, final String username, final Long cursor, final int size) {

if (query != null && !query.isEmpty()) {
log.info("event-keyword-search, {}", query);
saveSearchHistoryIfUserExists(username, query);
}

return postRepository.searchPostsByKeyword(query, username, cursor, size);
}

private void saveSearchHistoryIfUserExists(final String username, final String query) {
if (username == null) {
return;
Expand Down
Loading