Skip to content

Commit c31735c

Browse files
committed
Support composite key for spring-jdbc-plus-sql
1 parent a47c92c commit c31735c

File tree

19 files changed

+549
-99
lines changed

19 files changed

+549
-99
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.navercorp.spring.data.jdbc.plus.repository.guide.coupon;
2+
3+
import java.util.UUID;
4+
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.data.relational.core.mapping.Column;
7+
import org.springframework.data.relational.core.mapping.Embedded;
8+
import org.springframework.data.relational.core.mapping.Table;
9+
10+
import lombok.Builder;
11+
12+
@Table("coupon")
13+
@Builder(toBuilder = true)
14+
public record Coupon(
15+
@Id
16+
@Embedded.Nullable
17+
CouponId id,
18+
@Column("discount_amt")
19+
long discountAmount,
20+
String purchaserNo
21+
) {
22+
public record CouponId(
23+
String couponId,
24+
String pubtId
25+
) {
26+
public static CouponId generate() {
27+
return new CouponId(
28+
UUID.randomUUID().toString(),
29+
UUID.randomUUID().toString()
30+
);
31+
}
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.navercorp.spring.data.jdbc.plus.repository.guide.coupon;
2+
3+
import java.util.List;
4+
5+
import com.navercorp.spring.data.jdbc.plus.repository.JdbcRepository;
6+
import com.navercorp.spring.data.jdbc.plus.repository.guide.coupon.Coupon.CouponId;
7+
8+
public interface CouponRepository extends JdbcRepository<Coupon, CouponId> {
9+
List<Coupon> findByPurchaserNo(String purchaserNo);
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@org.jspecify.annotations.NullMarked
2+
package com.navercorp.spring.data.jdbc.plus.repository.guide.coupon;
3+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.navercorp.spring.data.jdbc.plus.repository.guide.coupon;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import java.util.List;
6+
7+
import org.junit.jupiter.api.Test;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.test.context.SpringBootTest;
10+
import org.springframework.test.context.ActiveProfiles;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
import com.navercorp.spring.data.jdbc.plus.repository.guide.coupon.Coupon.CouponId;
14+
15+
@SpringBootTest
16+
@ActiveProfiles("test")
17+
@Transactional
18+
class CouponRepositoryTest {
19+
20+
@Autowired
21+
private CouponRepository sut;
22+
23+
@Test
24+
void insert() {
25+
// given
26+
Coupon coupon = sample();
27+
28+
// when
29+
sut.insert(coupon);
30+
31+
// then
32+
assertThat(sut.findById(coupon.id())).hasValue(coupon);
33+
}
34+
35+
@Test
36+
void update() {
37+
// given
38+
Coupon coupon = sample();
39+
40+
// when
41+
sut.insert(coupon);
42+
sut.update(coupon.toBuilder()
43+
.discountAmount(40302L)
44+
.build());
45+
46+
// then
47+
assertThat(sut.findById(coupon.id())).hasValueSatisfying(actual -> {
48+
assertThat(actual.id()).isEqualTo(coupon.id());
49+
assertThat(actual.discountAmount()).isEqualTo(40302L);
50+
});
51+
}
52+
53+
@Test
54+
void findByPurchaserNo() {
55+
// given
56+
List<Coupon> coupons = List.of(
57+
sample(),
58+
sample(),
59+
sample(),
60+
sample(),
61+
sample()
62+
);
63+
64+
sut.insertAll(coupons);
65+
66+
// when
67+
List<Coupon> actual = sut.findByPurchaserNo("940329");
68+
69+
// then
70+
assertThat(actual).hasSize(5).allSatisfy(it -> {
71+
assertThat(it).isIn(coupons);
72+
});
73+
}
74+
75+
Coupon sample() {
76+
return new Coupon(CouponId.generate(), 1000L, "940329");
77+
}
78+
}
79+

guide-projects/plus-repository-guide/src/test/resources/data/schema.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,10 @@ CREATE TABLE IF NOT EXISTS plain_reviews (
8080
last_modified_at TIMESTAMP,
8181
visible TINYINT,
8282
PRIMARY KEY(id));
83+
84+
CREATE TABLE IF NOT EXISTS coupon (
85+
coupon_id VARCHAR(36),
86+
pubt_id VARCHAR(36),
87+
discount_amt BIGINT,
88+
purchaser_no VARCHAR(255),
89+
PRIMARY KEY(coupon_id, pubt_id));

guide-projects/plus-sql-java-kotlin-guide/src/main/java/com/navercorp/spring/data/jdbc/plus/sql/guide/board/Board.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.jspecify.annotations.Nullable;
2929
import org.springframework.data.annotation.Id;
30+
import org.springframework.data.domain.Persistable;
3031
import org.springframework.data.relational.core.mapping.Column;
3132
import org.springframework.data.relational.core.mapping.Embedded;
3233
import org.springframework.data.relational.core.mapping.MappedCollection;
@@ -73,11 +74,28 @@ public class Board {
7374
@Table("n_label")
7475
@Getter
7576
@Builder
76-
public static class Label {
77+
public static class Label implements Persistable<LabelId> {
7778
@Id
78-
private Long id;
79+
@Nullable
80+
@Embedded.Empty
81+
private LabelId id;
7982

8083
private String name;
84+
85+
@Override
86+
public boolean isNew() {
87+
return false;
88+
}
89+
}
90+
91+
@Value
92+
@Builder
93+
public static class LabelId {
94+
@Column("title")
95+
String title;
96+
97+
@Column("project_name")
98+
String projectName;
8199
}
82100

83101
@Table("n_post")

guide-projects/plus-sql-java-kotlin-guide/src/main/java/com/navercorp/spring/data/jdbc/plus/sql/guide/config/JdbcConfig.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.navercorp.spring.data.jdbc.plus.sql.guide.config;
22

3+
import org.springframework.context.annotation.Bean;
34
import org.springframework.context.annotation.Configuration;
45
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
6+
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
57

68
import jakarta.annotation.PostConstruct;
79
import lombok.RequiredArgsConstructor;
810

11+
import com.navercorp.spring.data.jdbc.plus.sql.guide.pay.PayHistory;
12+
913
@Configuration
1014
@RequiredArgsConstructor
1115
public class JdbcConfig {
@@ -15,4 +19,15 @@ public class JdbcConfig {
1519
public void init() {
1620
this.mappingContext.setSingleQueryLoadingEnabled(true);
1721
}
22+
23+
@Bean
24+
public BeforeConvertCallback<PayHistory> generatePayHistoryNo() {
25+
return (aggregate) -> {
26+
if (!aggregate.isNew()) {
27+
return aggregate;
28+
} else {
29+
return aggregate.generateId();
30+
}
31+
};
32+
}
1833
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.navercorp.spring.data.jdbc.plus.sql.guide.pay;
2+
3+
import java.util.concurrent.atomic.AtomicLong;
4+
5+
import org.jspecify.annotations.Nullable;
6+
import org.springframework.data.annotation.Id;
7+
import org.springframework.data.domain.Persistable;
8+
import org.springframework.data.relational.core.mapping.Column;
9+
import org.springframework.data.relational.core.mapping.Embedded;
10+
import org.springframework.data.relational.core.mapping.Table;
11+
12+
import lombok.With;
13+
14+
import com.navercorp.spring.data.jdbc.plus.sql.guide.pay.PayHistory.PayHistoryId;
15+
16+
@Table("n_pay_hist")
17+
public record PayHistory(
18+
@Id
19+
@With
20+
@Embedded.Empty
21+
PayHistoryId id,
22+
23+
long orderId,
24+
25+
@Column("pay_amt")
26+
long amount
27+
) implements Persistable<PayHistoryId> {
28+
public static PayHistory from(Pay pay) {
29+
return new PayHistory(
30+
PayHistoryId.from(pay),
31+
pay.orderId(),
32+
pay.amount().longValue()
33+
);
34+
}
35+
36+
@Override
37+
public PayHistoryId getId() {
38+
return id;
39+
}
40+
41+
@Override
42+
public boolean isNew() {
43+
return id.payHistoryNo == null;
44+
}
45+
46+
public PayHistory generateId() {
47+
return new PayHistory(id.generate(), orderId, amount);
48+
}
49+
50+
public record PayHistoryId(
51+
@Column("pay_no")
52+
long payNo,
53+
54+
@With
55+
@Nullable
56+
@Column("pay_hist_no")
57+
Long payHistoryNo
58+
) {
59+
private static final AtomicLong SEQUENCE = new AtomicLong(0);
60+
61+
public PayHistoryId generate() {
62+
return new PayHistoryId(payNo, SEQUENCE.incrementAndGet());
63+
}
64+
65+
static PayHistoryId from(Pay pay) {
66+
if (pay.id() == null) {
67+
throw new IllegalStateException("pay id is null");
68+
}
69+
70+
return new PayHistoryId(
71+
pay.id(),
72+
null
73+
);
74+
}
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.navercorp.spring.data.jdbc.plus.sql.guide.pay;
2+
3+
import java.util.List;
4+
5+
import org.springframework.data.repository.ListCrudRepository;
6+
7+
import com.navercorp.spring.data.jdbc.plus.sql.guide.pay.PayHistory.PayHistoryId;
8+
9+
public interface PayHistoryRepository
10+
extends ListCrudRepository<PayHistory, PayHistoryId>, PayHistoryRepositoryCustom {
11+
12+
List<PayHistory> findByOrderId(Long orderId);
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.navercorp.spring.data.jdbc.plus.sql.guide.pay;
2+
3+
import java.util.List;
4+
5+
public interface PayHistoryRepositoryCustom {
6+
List<PayHistory> findByOrderNo(long orderId);
7+
}

0 commit comments

Comments
 (0)