回答編集履歴
1
テーブルを 1 つにしたコードに全面変更
test
CHANGED
@@ -1,21 +1,7 @@
|
|
1
|
-
質問等の感じからして、あまり仕様を意識せずなんとなく作られていて、ある部分を作った時と別部分を作った時とでその瞬間の考えが違っていてあちこちで齟齬が起きているのではないでしょうか。
|
2
|
-
|
1
|
+
SELECT に関する情報が質問に追加されましたが、テーブルが 2 つあってどちらも有ったり無かったりするのが原因で複雑な処理・SELECT 文になっています。
|
2
|
+
テーブルを 1 つに纏めてしまえば id の問題も SELECT の複雑さも無くなり処理が簡単になります。
|
3
3
|
|
4
|
-
とりあえずネットワークは関係無さそうですのでデータベースの部分だけに注目してみます。
|
5
|
-
テキスト(とユーザ名)を保存する mutters テーブルと画像を保存して関係するテキストの id を持つ filepaths テーブルがあり、テキスト+画像、テキストのみ、画像のみの 3 パターンでテーブルに保存するメソッド insertTextAndImage を考えます。
|
6
|
-
仕様としては
|
7
|
-
|
8
|
-
- text があれば texts テーブルに保存する.
|
9
|
-
- image があれば images テーブルに保存する. この時 text もあって texts テーブルに保存していたら、 texts_id にその id を入れる.
|
10
|
-
|
11
|
-
の 2 点のみです。まずはこれだけをしっかり作ります。
|
12
|
-
テーブル構造がアプリに対して十分なのかは(現状こちらには情報がありませんので)考えません。
|
13
|
-
|
14
|
-
テキストの
|
4
|
+
テキストが無い時や画像が無い時等はぞれぞれのレコードを作らなければ何かの節約になると考えられたのかもしれませんが、そのような最適化を考えるのは時期尚早です。
|
15
|
-
このように小さな機能をメソッドとして完結するよう定義し、それらを組み合わせてより大きくしていく構造を意識しておくと、混乱し難いかもしれません。(個人の感想です。)
|
16
|
-
|
17
|
-
**※Spring を使わないため Image クラスはダミーを定義・利用しています。**
|
18
|
-
|
19
5
|
```java
|
20
6
|
import java.io.IOException;
|
21
7
|
import java.io.InputStream;
|
@@ -28,102 +14,71 @@
|
|
28
14
|
public static void main(String[] args) throws Exception {
|
29
15
|
try(Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "")) {
|
30
16
|
initTables(conn);
|
31
|
-
|
17
|
+
|
32
|
-
// 3パターンをテスト
|
18
|
+
// 3パターンをテスト(少し時間を開けて insert )
|
33
19
|
//text & image
|
34
|
-
insert
|
20
|
+
insertPost(conn, "Aaa", "ABCDEFG", "file1", new Image("type1", new byte[]{1,2,3,4}));
|
35
21
|
//text only
|
22
|
+
Thread.sleep(10);
|
36
|
-
insert
|
23
|
+
insertPost(conn, "Bbb", "abcdefg", null, null);
|
37
24
|
//image only
|
25
|
+
Thread.sleep(10);
|
38
|
-
insert
|
26
|
+
insertPost(conn, "Ccc", null, "file2", new Image("type2", new byte[]{5,6,7,8}));
|
39
27
|
|
40
28
|
//確認
|
41
29
|
printTables(conn);
|
42
30
|
}
|
43
31
|
}
|
44
32
|
|
45
|
-
static void insert
|
33
|
+
static void insertPost(Connection conn, String name, String text, String file_name, Image image) throws SQLException {
|
46
|
-
|
34
|
+
String sql = "INSERT INTO posts (name, datetime, text, image_name, image_type, image) VALUES (?, ?, ?, ?, ?, ?)";
|
47
35
|
|
36
|
+
try(PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
37
|
+
//共通
|
48
|
-
|
38
|
+
pstmt.setString(1, name);
|
39
|
+
pstmt.setTimestamp(2, new java.sql.Timestamp(System.currentTimeMillis()));
|
40
|
+
//テキスト
|
41
|
+
if(isValid(text)) {
|
42
|
+
pstmt.setString(3, text);
|
43
|
+
} else {
|
44
|
+
pstmt.setNull(3, Types.VARCHAR);
|
45
|
+
}
|
46
|
+
//画像
|
49
|
-
if(
|
47
|
+
if(isValid(file_name) && image != null) {
|
48
|
+
pstmt.setString(4, file_name);
|
50
|
-
te
|
49
|
+
pstmt.setString(5, image.getContentType());
|
50
|
+
pstmt.setBlob(6, image.getFileContent());
|
51
|
+
} else {
|
52
|
+
pstmt.setNull(4, Types.VARCHAR);
|
53
|
+
pstmt.setNull(5, Types.VARCHAR);
|
54
|
+
pstmt.setNull(6, Types.BLOB);
|
55
|
+
}
|
56
|
+
|
57
|
+
if(pstmt.executeUpdate() <= 0) {
|
58
|
+
throw new IllegalStateException();
|
59
|
+
}
|
51
60
|
}
|
52
|
-
|
53
|
-
if(image != null) {
|
54
|
-
insertImage(conn, texts_id, image.getFileContent(), image.getContentType());
|
55
|
-
}
|
56
|
-
|
57
|
-
conn.commit();
|
58
61
|
}
|
59
62
|
|
60
|
-
static int insertText(Connection conn, String name, String text) throws SQLException {
|
61
|
-
String sql = "INSERT INTO texts (name, text, tweet_date) VALUES (?, ?, ?)";
|
62
|
-
|
63
|
-
try(PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
|
64
|
-
|
65
|
-
pstmt.setString(1, name);
|
66
|
-
pstmt.setString(2, text);
|
67
|
-
pstmt.setDate(3, new java.sql.Date(System.currentTimeMillis()));
|
68
|
-
|
69
|
-
|
63
|
+
static boolean isValid(String s) {
|
70
|
-
try(ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
|
71
|
-
if(generatedKeys.next()) {
|
72
|
-
|
64
|
+
return s != null && !s.isEmpty();
|
73
|
-
}
|
74
|
-
}
|
75
|
-
}
|
76
|
-
}
|
77
|
-
throw new IllegalStateException();
|
78
65
|
}
|
79
66
|
|
80
|
-
static int insertImage(Connection conn, Integer texts_id, Blob content, String content_type) throws SQLException {
|
81
|
-
String sql = "INSERT INTO images (texts_id, content, content_type) VALUES (?, ?, ?)";
|
82
|
-
|
83
|
-
try(PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
|
84
|
-
|
85
|
-
if(texts_id == null) {
|
86
|
-
pstmt.setNull(1, Types.INTEGER);
|
87
|
-
} else {
|
88
|
-
pstmt.setInt(1, texts_id);
|
89
|
-
}
|
90
|
-
pstmt.setBlob(2, content);
|
91
|
-
pstmt.setString(3, content_type);
|
92
|
-
|
93
|
-
if(pstmt.executeUpdate() > 0) {
|
94
|
-
try(ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
|
95
|
-
if(generatedKeys.next()) {
|
96
|
-
return generatedKeys.getInt(1);
|
97
|
-
}
|
98
|
-
}
|
99
|
-
}
|
100
|
-
}
|
101
|
-
throw new IllegalStateException();
|
102
|
-
}
|
103
|
-
|
104
|
-
//テスト用 初期化
|
67
|
+
//テスト用 初期化
|
105
68
|
static void initTables(Connection conn) throws SQLException {
|
106
69
|
try(Statement stmt = conn.createStatement()) {
|
107
70
|
stmt.execute(
|
108
|
-
"DROP TABLE IF EXISTS images;"
|
109
|
-
+ "CREATE TABLE IF NOT EXISTS images ("
|
110
|
-
+ " id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,"
|
111
|
-
+ " texts_id INT,"
|
112
|
-
+ " content BLOB,"
|
113
|
-
+ " content_type VARCHAR(32),"
|
114
|
-
+ " update_at TIMESTAMP"
|
115
|
-
+ ");");
|
116
|
-
stmt.execute(
|
117
|
-
"DROP TABLE IF EXISTS t
|
71
|
+
"DROP TABLE IF EXISTS posts;"
|
118
|
-
+ "CREATE TABLE IF NOT EXISTS t
|
72
|
+
+ "CREATE TABLE IF NOT EXISTS posts ("
|
119
73
|
+ " id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,"
|
120
74
|
+ " name VARCHAR(200),"
|
121
|
-
+ " text VARCHAR(200),"
|
122
|
-
+ "
|
75
|
+
+ " datetime DATETIME,"
|
76
|
+
+ " text VARCHAR(200)," //テキスト投稿(テキストが無いときは null)
|
77
|
+
+ " image_name VARCHAR(200)," //画像投稿(画像が無いときは null)
|
78
|
+
+ " image_type VARCHAR(32)," //同上
|
79
|
+
+ " image BLOB" //同上
|
123
|
-
+ ")"
|
80
|
+
+ ");"
|
124
|
-
|
125
|
-
stmt.execute("DELETE FROM filepaths");
|
126
|
-
|
81
|
+
+ "DELETE FROM posts;");
|
127
82
|
}
|
128
83
|
}
|
129
84
|
|
@@ -142,24 +97,16 @@
|
|
142
97
|
//テスト用 確認表示
|
143
98
|
private static void printTables(Connection conn) throws SQLException {
|
144
99
|
try(Statement stmt = conn.createStatement()) {
|
145
|
-
System.out.println("-- t
|
100
|
+
System.out.println("-- posts --------");
|
146
|
-
try(ResultSet rs = stmt.executeQuery("SELECT
|
101
|
+
try(ResultSet rs = stmt.executeQuery("SELECT id, name, datetime, text, image_name, image_type, image FROM posts ORDER BY datetime DESC")) {
|
147
102
|
while(rs.next()) {
|
148
103
|
System.out.println("ID=" + rs.getInt(1));
|
149
104
|
System.out.println("name=" + rs.getString(2));
|
105
|
+
System.out.println("datetime=" + rs.getTimestamp(3));
|
150
|
-
System.out.println("text=" + rs.getString(
|
106
|
+
System.out.println("text=" + rs.getString(4));
|
107
|
+
System.out.println("image_name=" + rs.getString(5));
|
151
|
-
System.out.println("
|
108
|
+
System.out.println("image_type=" + rs.getString(6));
|
152
|
-
}
|
153
|
-
}
|
154
|
-
System.out.println("-- images --------");
|
155
|
-
try(ResultSet rs = stmt.executeQuery("SELECT * FROM images")) {
|
156
|
-
while(rs.next()) {
|
157
|
-
System.out.println("ID=" + rs.getInt(1));
|
158
|
-
Integer texts_id = rs.getInt(2);
|
159
|
-
if(rs.wasNull()) texts_id = null;
|
160
|
-
System.out.println("texts_id=" + texts_id);
|
161
|
-
System.out.println("
|
109
|
+
System.out.println("image=" + toString(rs.getBlob(7)));
|
162
|
-
System.out.println("content_type=" + rs.getString(4));
|
163
110
|
}
|
164
111
|
}
|
165
112
|
}
|
@@ -167,6 +114,7 @@
|
|
167
114
|
|
168
115
|
//テスト用 Blob 表示
|
169
116
|
private static String toString(Blob blob) throws SQLException {
|
117
|
+
if(blob == null) return "null";
|
170
118
|
StringJoiner sj = new StringJoiner(",");
|
171
119
|
try(InputStream is = blob.getBinaryStream()) {
|
172
120
|
for(int c ; (c=is.read())!=-1; ) sj.add(String.format("%d", c&0xff));
|
@@ -177,24 +125,27 @@
|
|
177
125
|
}
|
178
126
|
}
|
179
127
|
```
|
180
|
-
実行結果
|
181
128
|
```
|
182
|
-
-- t
|
129
|
+
-- posts --------
|
130
|
+
ID=3
|
131
|
+
name=Ccc
|
132
|
+
datetime=2024-03-03 02:01:07.598
|
133
|
+
text=null
|
134
|
+
image_name=file2
|
135
|
+
image_type=type2
|
136
|
+
image=5,6,7,8
|
137
|
+
ID=2
|
138
|
+
name=Bbb
|
139
|
+
datetime=2024-03-03 02:01:07.582
|
140
|
+
text=abcdefg
|
141
|
+
image_name=null
|
142
|
+
image_type=null
|
143
|
+
image=null
|
183
144
|
ID=1
|
184
145
|
name=Aaa
|
146
|
+
datetime=2024-03-03 02:01:07.563
|
185
147
|
text=ABCDEFG
|
186
|
-
date=2024-02-29
|
187
|
-
ID=2
|
188
|
-
name=Bbb
|
189
|
-
text=abcdefg
|
190
|
-
date=2024-02-29
|
191
|
-
|
148
|
+
image_name=file1
|
192
|
-
ID=1
|
193
|
-
te
|
149
|
+
image_type=type1
|
194
|
-
|
150
|
+
image=1,2,3,4
|
195
|
-
content_type=test1
|
196
|
-
ID=2
|
197
|
-
texts_id=null
|
198
|
-
content=5,6,7,8
|
199
|
-
content_type=test2
|
200
151
|
```
|