teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

修正

2020/03/15 14:19

投稿

rubytomato
rubytomato

スコア1752

answer CHANGED
File without changes

2

修正

2020/03/15 14:19

投稿

rubytomato
rubytomato

スコア1752

answer CHANGED
@@ -201,7 +201,7 @@
201
201
  String messageContent = messageForm.getMessageContent();
202
202
 
203
203
  Message message = new Message();
204
- message.setMessageContent(messageForm.getMessageContent());
204
+ message.setMessageContent(messageContent);
205
205
  message.setMessageTime(new Date());
206
206
  message.setSenderUser(senderUser);
207
207
  message.setReceiverUser(receiverUser);

1

追記

2020/03/15 14:19

投稿

rubytomato
rubytomato

スコア1752

answer CHANGED
@@ -42,4 +42,175 @@
42
42
  // ↓ ちなみにこの書き方だと期待するリダイレクトになりません。
43
43
  return "redirect:{userId}/message";
44
44
  }
45
+ ```
46
+
47
+ **追記**
48
+
49
+ 以下は私だったらこう実装するという意味の内容です。なのでこうしなければならないという訳ではなく、あくまで参考程度のものです。また、コード全体ではなく必要な個所だけ抜粋しています。
50
+
51
+ エンティティクラス
52
+
53
+ ```java
54
+ @Entity
55
+ @NamedQuery(name="Message.findAll", query="SELECT m FROM Message m")
56
+ public class Message implements Serializable {
57
+
58
+ @Id
59
+ @GeneratedValue(strategy=GenerationType.IDENTITY)
60
+ @Column(name="message_id")
61
+ // フィールドの型にプリミティブ型は使用しない
62
+ //private long messageId;
63
+ private Long messageId;
64
+
65
+ //処理のないデフォルトコンストラクタは書かない
66
+ //public Message() {
67
+ //}
68
+
69
+ public void setSenderUser(User senderUser) {
70
+ this.senderUser = senderUser;
71
+ this.senderUser.addSendMessage(this);
72
+ }
73
+
74
+ public void setReceiverUser(User receiverUser) {
75
+ this.receiverUser = receiverUser;
76
+ this.receiverUser.addReceiveMessage(this);
77
+ }
78
+
79
+ }
80
+ ```
81
+
82
+ ```java
83
+ @Entity
84
+ //Transactionalアノテーションはトランザクション境界を考えて付与する
85
+ //@Transactional
86
+ @NamedQuery(name="User.findAll", query="SELECT u FROM User u")
87
+ public class User implements Serializable {
88
+
89
+ @Id
90
+ @Column(name="user_id")
91
+ // フィールドの型にプリミティブ型は使用しない
92
+ //private int userId;
93
+ private Integer userId;
94
+
95
+ @OneToMany(mappedBy="senderUser")
96
+ //意味の通じにくいフィールド名は避ける
97
+ //private List<Message> messages1;
98
+ private List<Message> sendMessages;
99
+
100
+ @OneToMany(mappedBy="receiverUser")
101
+ //意味の通じにくいフィールド名は避ける
102
+ //private List<Message> messages2;
103
+ private List<Message> receiveMessages;
104
+
105
+ //処理のないデフォルトコンストラクタは書かない
106
+ //public User() {
107
+ //}
108
+
109
+ public void addSendMessage(Message message) {
110
+ if (this.sendMessages == null) {
111
+ this.sendMessages = new ArrayList<>();
112
+ }
113
+ this.sendMessages.add(message);
114
+ }
115
+
116
+ public void addReceiveMessage(Message message) {
117
+ if (this.receiveMessages == null) {
118
+ this.receiveMessages = new ArrayList<>();
119
+ }
120
+ this.receiveMessages.add(message);
121
+ }
122
+
123
+ }
124
+ ```
125
+
126
+ リポジトリインターフェース
127
+ (※`MessageReposioty`は`MessageRepository`のtypoです)
128
+
129
+ ```java
130
+ //不要なアノテーションは付与しない
131
+ //@Repository
132
+ //Transactionalアノテーションはトランザクション境界を考えて付与する
133
+ //@Transactional
134
+ public interface MessageRepository extends JpaRepository<Message, Long> {
135
+ //プリミティブ型を避ける
136
+ //List<Message> findBySenderUser_UserId(int userId);
137
+ //List<Message> findByReceiverUser_UserId(int userId);
138
+ List<Message> findBySenderUser_UserId(Integer userId);
139
+ List<Message> findByReceiverUser_UserId(Integer userId);
140
+
141
+ //可能な限りネイティブクエリを避ける
142
+ //今回はsaveメソッドで十分なので使用しない
143
+ //@Modifying
144
+ //@Query(value = "insert into message (sender_user_id,receiver_user_id,message_content) "
145
+ // + "VALUES (:senderUserId,:receiverUserId,:messageContent)", nativeQuery = true)
146
+ //@Transactional
147
+ //void sendMessage(@Param("senderUserId") int senderUserId, @Param("receiverUserId") int receiverUserId,
148
+ // @Param("messageContent") String messageContent);
149
+
150
+ }
151
+ ```
152
+
153
+ コントローラクラス
154
+
155
+ ```java
156
+ @Controller
157
+ @RequestMapping("profile")
158
+ public class MessageController {
159
+
160
+ //コンストラクタインジェクションを利用する
161
+ //@Autowired
162
+ //UserRepository userRepository;
163
+ //@Autowired
164
+ //MessageRepository messageRepository;
165
+
166
+ private final UserRepository userRepository;
167
+ private final MessageRepository messageRepository;
168
+
169
+ public MessageController(UserRepository userRepository, MessageRepository messageRepository) {
170
+ this.userRepository = userRepository;
171
+ this.messageRepository = messageRepository;
172
+ }
173
+
174
+ //送信時の処理
175
+ @PostMapping("/{userId}/message")
176
+ // トランザクション境界をここに設定する(この例では)
177
+ // 本来ならサービスクラスを実装しそのメソッドにトランザクション境界を設定する
178
+ @Transactional(readOnly = false, timeout = 10)
179
+ String sendMessage(@Validated MessageForm messageForm,
180
+ // バリデーションを行うのならBindingResultでその結果を受け取る
181
+ BindingResult result,
182
+ @AuthenticationPrincipal LoginUserDetails userDetails,
183
+ @PathVariable("userId") Integer userId
184
+ // 使用しない引数は定義しない
185
+ /* Model model */) {
186
+
187
+ if (result.hasErrors()) {
188
+ // バリデーションエラー時の処理
189
+ }
190
+
191
+ //User senderUser = userDetails.getUser();
192
+ User senderUser = userRepository.findById(userDetails.getUser().getUserId()).orElseThrow();
193
+
194
+ //安易にnullを返さない。検索できなかったときにどうするか仕様を決めておく。
195
+ //User receiverUser = userRepository.findById(userId).orElse(null);
196
+ User receiverUser = userRepository.findById(userId).orElseThrow();
197
+
198
+ //int senderUserId = senderUser.getUserId();
199
+ //int receiverUserId = receiverUser.getUserId();
200
+
201
+ String messageContent = messageForm.getMessageContent();
202
+
203
+ Message message = new Message();
204
+ message.setMessageContent(messageForm.getMessageContent());
205
+ message.setMessageTime(new Date());
206
+ message.setSenderUser(senderUser);
207
+ message.setReceiverUser(receiverUser);
208
+ messageRepository.save(message);
209
+
210
+ //リポジトリのsaveメソッドで永続化するので使用しない
211
+ //messageRepository.sendMessage(senderUserId, receiverUserId, messageContent);
212
+ return "redirect:/profile/" + userId + "/message";
213
+ }
214
+
215
+ }
45
216
  ```