blob: 1141c5bff2ef5d3f446df782aa9dfad44989b46d [file] [log] [blame]
rootcd436562025-05-08 14:09:19 +00001package cheat;
2
Raver5ba779f2025-05-14 12:48:12 +00003import java.util.ArrayList;
rhje18c3f72025-06-08 00:27:01 +08004import java.util.HashMap;
Raver5ba779f2025-05-14 12:48:12 +00005import java.util.List;
rhje18c3f72025-06-08 00:27:01 +08006import java.util.Map;
TRM-coding508b31f2025-06-09 02:07:14 +08007import java.util.HashMap;
Raver5ba779f2025-05-14 12:48:12 +00008
9import javax.persistence.EntityManager;
rhje18c3f72025-06-08 00:27:01 +080010import javax.persistence.EntityManagerFactory;
11import javax.persistence.Persistence;
Raverf79fdb62025-06-03 06:02:49 +000012import javax.persistence.PersistenceContext;
13import javax.transaction.Transactional;
Raver5ba779f2025-05-14 12:48:12 +000014
15import org.apache.commons.lang3.tuple.Pair;
rhje18c3f72025-06-08 00:27:01 +080016import java.io.File;
17import java.nio.file.Files;
18import java.nio.file.Path;
19import java.nio.file.Paths;
20import java.nio.file.StandardCopyOption;
Raver5ba779f2025-05-14 12:48:12 +000021
22import com.querydsl.jpa.impl.JPAQueryFactory;
23
TRM-coding508b31f2025-06-09 02:07:14 +080024import entity.Seed;
Raver5ba779f2025-05-14 12:48:12 +000025import entity.Appeal;
26import entity.QAppeal;
27import entity.QSeed;
28import entity.User;
29import entity.config;
rhje18c3f72025-06-08 00:27:01 +080030import entity.QUser;
31import entity.TTorent;
TRM-coding508b31f2025-06-09 02:07:14 +080032import entity.QTransRecord;
33import entity.TransRecord;
Raver5ba779f2025-05-14 12:48:12 +000034
35public class Cheat implements CheatInterfnterface {
36
Raverf79fdb62025-06-03 06:02:49 +000037 @PersistenceContext
rhje18c3f72025-06-08 00:27:01 +080038 private EntityManagerFactory emf;
39
40 public Cheat() {
41 config cfg = new config();
42 Map<String,Object> props = new HashMap<>();
43 props.put("javax.persistence.jdbc.url",
44 "jdbc:mysql://" + cfg.SqlURL + "/" + cfg.Database);
45 props.put("javax.persistence.jdbc.user", cfg.SqlUsername);
46 props.put("javax.persistence.jdbc.password", cfg.SqlPassword);
47 this.emf = Persistence.createEntityManagerFactory("myPersistenceUnit", props);
48 }
Raver5ba779f2025-05-14 12:48:12 +000049
50 @Override
Raverf79fdb62025-06-03 06:02:49 +000051 @Transactional
Raver5ba779f2025-05-14 12:48:12 +000052 public boolean AddAppeal(Appeal appeal) {
rhje18c3f72025-06-08 00:27:01 +080053 EntityManager entityManager = emf.createEntityManager();
Raver5ba779f2025-05-14 12:48:12 +000054 try {
rhje18c3f72025-06-08 00:27:01 +080055 entityManager.getTransaction().begin();
Raverf79fdb62025-06-03 06:02:49 +000056 entityManager.persist(appeal);
rhje18c3f72025-06-08 00:27:01 +080057 entityManager.getTransaction().commit();
Raver5ba779f2025-05-14 12:48:12 +000058 } catch (Exception e) {
59 e.printStackTrace();
rhje18c3f72025-06-08 00:27:01 +080060 if (entityManager.getTransaction().isActive()) {
61 entityManager.getTransaction().rollback();
62 }
Raver5ba779f2025-05-14 12:48:12 +000063 return false;
64 }
65 return true;
66 }
67
68 @Override
69 public Appeal GetAppeal(String appealid) {
70 try {
rhje18c3f72025-06-08 00:27:01 +080071 EntityManager entityManager = emf.createEntityManager();
Raverf79fdb62025-06-03 06:02:49 +000072 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
Raver5ba779f2025-05-14 12:48:12 +000073 QAppeal qAppeal = QAppeal.appeal;
74 Appeal appeal = queryFactory
Raverf79fdb62025-06-03 06:02:49 +000075 .selectFrom(qAppeal)
76 .where(qAppeal.appealid.eq(appealid))
77 .fetchOne();
Raver5ba779f2025-05-14 12:48:12 +000078 return appeal;
79 } catch (Exception e) {
80 e.printStackTrace();
81 return null;
82 }
83 }
84
85 @Override
86 public Appeal[] GetAppealList() {
rhje18c3f72025-06-08 00:27:01 +080087 EntityManager entityManager = emf.createEntityManager();
Raver5ba779f2025-05-14 12:48:12 +000088 try {
Raverf79fdb62025-06-03 06:02:49 +000089 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
Raver5ba779f2025-05-14 12:48:12 +000090 QAppeal qAppeal = QAppeal.appeal;
91 List<Appeal> appeals = queryFactory
Raverf79fdb62025-06-03 06:02:49 +000092 .selectFrom(qAppeal)
93 .fetch();
Raver5ba779f2025-05-14 12:48:12 +000094 return appeals.toArray(new Appeal[0]);
95 } catch (Exception e) {
96 e.printStackTrace();
97 return null;
rhje18c3f72025-06-08 00:27:01 +080098 } finally {
99 if (entityManager != null) {
100 entityManager.close();
101 }
Raver5ba779f2025-05-14 12:48:12 +0000102 }
103 }
104
105 @Override
106 public boolean HandleAppeal(String appealid, Integer status) {
rhje18c3f72025-06-08 00:27:01 +0800107 EntityManager entityManager = emf.createEntityManager();
Raver5ba779f2025-05-14 12:48:12 +0000108 try {
Raverf79fdb62025-06-03 06:02:49 +0000109 Appeal appeal = GetAppeal(appealid);
Raver5ba779f2025-05-14 12:48:12 +0000110 if (appeal != null) {
111 appeal.status = status;
rhje18c3f72025-06-08 00:27:01 +0800112 entityManager.getTransaction().begin();
Raverf79fdb62025-06-03 06:02:49 +0000113 entityManager.merge(appeal);
114 User user = entityManager.find(User.class, appeal.appealuserid);
rhje18c3f72025-06-08 00:27:01 +0800115 // if (user != null && user.accountstate != false) {
116 if (user != null) {
Raver5ba779f2025-05-14 12:48:12 +0000117 if (status == 1) {
118 user.accountstate = false;
119 }
Raverf79fdb62025-06-03 06:02:49 +0000120 entityManager.merge(user);
Raver5ba779f2025-05-14 12:48:12 +0000121 }
rhje18c3f72025-06-08 00:27:01 +0800122 entityManager.getTransaction().commit();
Raver5ba779f2025-05-14 12:48:12 +0000123 return true;
124 }
125 return false;
126 } catch (Exception e) {
127 e.printStackTrace();
rhje18c3f72025-06-08 00:27:01 +0800128 if (emf.createEntityManager().getTransaction().isActive()) {
129 emf.createEntityManager().getTransaction().rollback();
130 }
Raver5ba779f2025-05-14 12:48:12 +0000131 return false;
rhje18c3f72025-06-08 00:27:01 +0800132 } finally {
133 if (entityManager != null) {
134 entityManager.close();
135 }
Raver5ba779f2025-05-14 12:48:12 +0000136 }
137 }
138
139 @Override
140 public Pair<String, String>[] GetFakeSeed() {
141 List<Pair<String, String>> fakeSeeds = new ArrayList<>();
142 try {
rhje18c3f72025-06-08 00:27:01 +0800143 EntityManager entityManager = emf.createEntityManager();
Raverf79fdb62025-06-03 06:02:49 +0000144 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
Raver5ba779f2025-05-14 12:48:12 +0000145 QSeed qSeed = QSeed.seed;
146 List<com.querydsl.core.Tuple> results = queryFactory
Raverf79fdb62025-06-03 06:02:49 +0000147 .select(qSeed.seedid, qSeed.seeduserid)
148 .from(qSeed)
rhje18c3f72025-06-08 00:27:01 +0800149 .where(qSeed.faketime.gt(config.getFakeTime()))
Raverf79fdb62025-06-03 06:02:49 +0000150 .fetch();
Raver5ba779f2025-05-14 12:48:12 +0000151 for (com.querydsl.core.Tuple result : results) {
152 String seedid = result.get(qSeed.seedid);
Raverf79fdb62025-06-03 06:02:49 +0000153 String userid = result.get(qSeed.seeduserid);
Raver5ba779f2025-05-14 12:48:12 +0000154 fakeSeeds.add(Pair.of(seedid, userid));
155 }
156 } catch (Exception e) {
157 e.printStackTrace();
158 return null;
159 }
160 return fakeSeeds.toArray(new Pair[0]);
161 }
162
163 @Override
164 public String[] GetPunishedUserList() {
165 List<String> punishedUsers = new ArrayList<>();
166 try {
rhje18c3f72025-06-08 00:27:01 +0800167 EntityManager entityManager = emf.createEntityManager();
Raverf79fdb62025-06-03 06:02:49 +0000168 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
Raver5ba779f2025-05-14 12:48:12 +0000169 entity.QUser qUser = entity.QUser.user;
170 List<String> results = queryFactory
Raverf79fdb62025-06-03 06:02:49 +0000171 .select(qUser.userid)
172 .from(qUser)
173 .where(qUser.accountstate.isTrue())
174 .fetch();
Raver5ba779f2025-05-14 12:48:12 +0000175 for (String userid : results) {
176 punishedUsers.add(userid);
177 }
178 } catch (Exception e) {
179 e.printStackTrace();
180 return null;
181 }
182 return punishedUsers.toArray(new String[0]);
183 }
184
185 @Override
186 public void DetectTrans() {
TRM-coding508b31f2025-06-09 02:07:14 +0800187 EntityManager entityManager = emf.createEntityManager();
188 try {
189 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
190 QSeed qSeed = QSeed.seed;
191 QTransRecord qTransRecord = QTransRecord.transRecord;
192
193 // 获取所有种子
194 List<Seed> seeds = queryFactory
195 .selectFrom(qSeed)
196 .fetch();
Raver5ba779f2025-05-14 12:48:12 +0000197
TRM-coding508b31f2025-06-09 02:07:14 +0800198 // 存储每个种子的delta值
199 List<Double> allDeltas = new ArrayList<>();
200 Map<String, Double> seedDeltaMap = new HashMap<>();
201
202 // 计算每个种子的delta值(只考虑account_status不为1的用户)
203 for (Seed seed : seeds) {
204 List<TransRecord> tasks = queryFactory
205 .selectFrom(qTransRecord)
206 .leftJoin(qTransRecord.uploader).fetchJoin()
207 .leftJoin(qTransRecord.downloader).fetchJoin()
208 .where(qTransRecord.seedid.eq(seed.seedid))
209 .fetch();
Raverf79fdb62025-06-03 06:02:49 +0000210
TRM-coding508b31f2025-06-09 02:07:14 +0800211 // 过滤掉account_status为1的用户的记录
212 List<TransRecord> validTasks = new ArrayList<>();
213 for (TransRecord task : tasks) {
214 boolean shouldInclude = true;
215
216 // 检查上传者
217 if (task.uploaduserid != null) {
218 User uploader = entityManager.find(User.class, task.uploaduserid);
219 if (uploader != null && uploader.accountstate) {
220 shouldInclude = false;
221 }
222 }
223
224 // 检查下载者
225 if (task.downloaduserid != null) {
226 User downloader = entityManager.find(User.class, task.downloaduserid);
227 if (downloader != null && downloader.accountstate) {
228 shouldInclude = false;
229 }
230 }
231
232 if (shouldInclude) {
233 validTasks.add(task);
234 }
235 }
Raverf79fdb62025-06-03 06:02:49 +0000236
TRM-coding508b31f2025-06-09 02:07:14 +0800237 if (validTasks.isEmpty()) continue;
Raverf79fdb62025-06-03 06:02:49 +0000238
TRM-coding508b31f2025-06-09 02:07:14 +0800239 // 计算该种子的总delta
240 double totalDelta = 0;
241 for (TransRecord task : validTasks) {
242 long upload = task.upload != null ? task.upload : 0L;
243 long download = task.download != null ? task.download : 0L;
244 totalDelta += (upload - download);
245 }
Raverf79fdb62025-06-03 06:02:49 +0000246
TRM-coding508b31f2025-06-09 02:07:14 +0800247 allDeltas.add(totalDelta);
248 seedDeltaMap.put(seed.seedid, totalDelta);
249 }
250
251 if (allDeltas.size() < 2) return; // 需要至少2个种子才能计算标准差
252
253 // 计算平均值和标准差
254 double sum = 0;
255 for (double delta : allDeltas) {
256 sum += delta;
257 }
258 double mean = sum / allDeltas.size();
259
260 double variance = 0;
261 for (double delta : allDeltas) {
262 variance += Math.pow(delta - mean, 2);
263 }
264 double stdDev = Math.sqrt(variance / allDeltas.size());
265
266 // 检测异常种子并处理参与者
267 for (Seed seed : seeds) {
268 Double seedDelta = seedDeltaMap.get(seed.seedid);
269 if (seedDelta == null) continue;
270
271 // 检查是否偏离1个标准差
272 if (Math.abs(seedDelta - mean) > stdDev) {
273 // 获取该种子的所有传输记录参与者
274 List<TransRecord> suspiciousTasks = queryFactory
275 .selectFrom(qTransRecord)
276 .where(qTransRecord.seedid.eq(seed.seedid))
277 .fetch();
278
279 // 更新所有参与者的detectedCount
280 for (TransRecord task : suspiciousTasks) {
281 // 处理上传者
282 if (task.uploaduserid != null) {
283 User uploader = entityManager.find(User.class, task.uploaduserid);
284 if (uploader != null && !uploader.accountstate) {
285 uploader.detectedCount++;
286 uploader.lastDetectedTime = new java.util.Date();
287 entityManager.merge(uploader);
288 }
289 }
290
291 // 处理下载者
292 if (task.downloaduserid != null) {
293 User downloader = entityManager.find(User.class, task.downloaduserid);
294 if (downloader != null && !downloader.accountstate) {
295 downloader.detectedCount++;
296 downloader.lastDetectedTime = new java.util.Date();
297 entityManager.merge(downloader);
298 }
299 }
300 }
301 }
302 }
303 } finally {
304 if (entityManager != null) {
305 entityManager.close();
306 }
307 }
Raver5ba779f2025-05-14 12:48:12 +0000308 }
309
310 @Override
TRM-coding508b31f2025-06-09 02:07:14 +0800311 @Transactional
Raverf79fdb62025-06-03 06:02:49 +0000312 public void DetectFakeSeed(){
TRM-coding508b31f2025-06-09 02:07:14 +0800313 EntityManager entityManager = emf.createEntityManager();
314 try {
315 String torrentDir = entity.config.TORRENT_STORAGE_DIR;
316 String scriptPath = "./src/main/java/cheat/fakeSeed.bash";
317
318 ProcessBuilder processBuilder = new ProcessBuilder("bash", scriptPath, torrentDir);
319 processBuilder.inheritIO();
320
321 Process process = processBuilder.start();
322 int exitCode = process.waitFor();
323
324 if (exitCode == 0) {
325 System.out.println("FakeSeed detection completed successfully");
326
327 // 处理检测结果
328 String failedDir = torrentDir + "/failed_torrents";
329 java.io.File failedDirFile = new java.io.File(failedDir);
330
331 // 获取失败种子文件列表
332 java.util.Set<String> failedTorrentNames = new java.util.HashSet<>();
333 if (failedDirFile.exists() && failedDirFile.isDirectory()) {
334 java.io.File[] failedFiles = failedDirFile.listFiles((dir, name) -> name.endsWith(".torrent"));
335 if (failedFiles != null) {
336 for (java.io.File file : failedFiles) {
337 failedTorrentNames.add(file.getName());
338 }
339 }
340 }
341
342 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
343 QSeed qSeed = QSeed.seed;
344
345 // 收集假种子的拥有者
346 java.util.Set<String> fakeOwners = new java.util.HashSet<>();
347
348 // 更新数据库中的fake_hits字段
349 List<Seed> allSeeds = queryFactory
350 .selectFrom(qSeed)
351 .where(qSeed.url.isNotNull())
352 .fetch();
353
354 for (Seed seed : allSeeds) {
355 java.io.File seedFile = new java.io.File(seed.url);
356 String fileName = seedFile.getName();
357
358 if (failedTorrentNames.contains(fileName)) {
359 // 失败种子,fake_hits + 1
360 seed.faketime++;
361 seed.lastfakecheck = new java.util.Date();
362 fakeOwners.add(seed.seeduserid);
363 System.out.println("Found fake seed: " + seed.seedid + " (fake_hits: " + seed.faketime + ")");
364 } else {
365 // 正常种子,fake_hits 清零
366 if (seed.faketime > 0) {
367 seed.faketime = 0;
368 seed.lastfakecheck = new java.util.Date();
369 System.out.println("Reset fake_hits for seed: " + seed.seedid);
370 }
371 }
372 entityManager.merge(seed);
373 }
374
375 // 更新所有用户的 fakeDetectedCount 和 fakeLastDetectedTime
376 entity.QUser qUser = entity.QUser.user;
377 List<User> allUsers = queryFactory
378 .selectFrom(qUser)
379 .fetch();
380
381 java.util.Date now = new java.util.Date();
382 for (User user : allUsers) {
383 if (fakeOwners.contains(user.userid)) {
384 // 假种子拥有者,fakeDetectedCount + 1
385 user.fakeDetectedCount++;
386 System.out.println("Increased fake detection count for user: " + user.userid + " (count: " + user.fakeDetectedCount + ")");
387 } else {
388 // 其他用户,fakeDetectedCount 清零
389 if (user.fakeDetectedCount > 0) {
390 user.fakeDetectedCount = 0;
391 System.out.println("Reset fake detection count for user: " + user.userid);
392 }
393 }
394 // 更新所有用户的检测时间
395 user.fakeLastDetectedTime = now;
396 entityManager.merge(user);
397 }
398
399 System.out.println("Fake seed detection and database update completed");
400 } else {
401 System.err.println("FakeSeed detection failed with exit code: " + exitCode);
402 }
403 } catch (Exception e) {
404 System.err.println("Error running FakeSeed detection script: " + e.getMessage());
405 e.printStackTrace();
406 } finally {
407 if (entityManager != null) {
408 entityManager.close();
409 }
410 }
Raver5ba779f2025-05-14 12:48:12 +0000411 }
412
413 @Override
Raverf79fdb62025-06-03 06:02:49 +0000414 public boolean DetectFakeSeed(String seedid){
Raver5ba779f2025-05-14 12:48:12 +0000415 return false;
416 }
417
418 @Override
Raverf79fdb62025-06-03 06:02:49 +0000419 public void PunishUser(){
rhje18c3f72025-06-08 00:27:01 +0800420 EntityManager entityManager = emf.createEntityManager();
Raverf79fdb62025-06-03 06:02:49 +0000421 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
422 entity.QUser qUser = entity.QUser.user;
423 List<User> users = queryFactory
424 .selectFrom(qUser)
rhje18c3f72025-06-08 00:27:01 +0800425 .where(qUser.detectedCount.gt(config.getCheatTime())
426 .or(qUser.fakeDetectedCount.gt(config.getFakeTime())))
Raverf79fdb62025-06-03 06:02:49 +0000427 .fetch();
Raver5ba779f2025-05-14 12:48:12 +0000428
Raverf79fdb62025-06-03 06:02:49 +0000429 for (User user : users) {
430 user.accountstate = true;
431 entityManager.merge(user);
Raver5ba779f2025-05-14 12:48:12 +0000432 }
433 }
rhje18c3f72025-06-08 00:27:01 +0800434
435 @Override
436 public User[] GetCheatUsers() {
437 EntityManager entityManager = emf.createEntityManager();
438 List<User> cheatUsers = new ArrayList<>();
439 try {
440 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
441 QUser qUser = QUser.user;
442 cheatUsers = queryFactory
443 .selectFrom(qUser)
444 .where(qUser.accountstate.eq(true))
445 .fetch();
446 return cheatUsers.toArray(new User[0]);
447 } catch (Exception e) {
448 e.printStackTrace();
449 return null;
450 } finally {
451 if (entityManager != null){
452 entityManager.close();
453 }
454 }
455 }
456
457 @Override
458 public User[] GetSuspiciousUsers() {
459 EntityManager entityManager = emf.createEntityManager();
460 List<User> suspiciousUsers = new ArrayList<>();
461 try {
462 JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
463 QUser qUser = QUser.user;
464 suspiciousUsers = queryFactory
465 .selectFrom(qUser)
466 .where((qUser.detectedCount.gt(0)
467 .or(qUser.fakeDetectedCount.gt(0)))
468 .and(qUser.accountstate.eq(false)))
469 .fetch();
470 return suspiciousUsers.toArray(new User[0]);
471 } catch (Exception e) {
472 e.printStackTrace();
473 return null;
474 } finally {
475 if (entityManager != null){
476 entityManager.close();
477 }
478 }
479 }
480
481 @Override
482 public int UnbanUser(String userid) {
483 EntityManager entityManager = emf.createEntityManager();
484 try {
485 User user = entityManager.find(User.class, userid);
486 if (user == null) {
487 return 1; // 用户不存在
488 }
489 if (user.accountstate) {
490 user.accountstate = false; // 解封用户
491 entityManager.getTransaction().begin();
492 entityManager.merge(user);
493 entityManager.getTransaction().commit();
494 return 0; // 成功解封
495 }
496 return 2; // 用户未被封禁
497 } catch (Exception e) {
498 e.printStackTrace();
499 if (entityManager.getTransaction().isActive()) {
500 entityManager.getTransaction().rollback();
501 }
502 return -1; // 出现异常
503 } finally {
504 if (entityManager != null){
505 entityManager.close();
506 }
507 }
508 }
509
510 @Override
511 public int BanUser(String userid) {
512 EntityManager entityManager = emf.createEntityManager();
513 try {
514 User user = entityManager.find(User.class, userid);
515 if (user == null) {
516 return 1; // 用户不存在
517 }
518 if (!user.accountstate) {
519 user.accountstate = true; // 封禁用户
520 entityManager.getTransaction().begin();
521 entityManager.merge(user);
522 entityManager.getTransaction().commit();
523 return 0; // 成功封禁
524 }
525 return 2; // 用户已被封禁
526 } catch (Exception e) {
527 e.printStackTrace();
528 if (entityManager.getTransaction().isActive()) {
529 entityManager.getTransaction().rollback();
530 }
531 return -1; // 出现异常
532 } finally {
533 if (entityManager != null){
534 entityManager.close();
535 }
536 }
537 }
538
539 @Override
540 public int SubmitAppeal(String userid, String content, File file) {
541 EntityManager entityManager = emf.createEntityManager();
542 try {
543 User user = entityManager.find(User.class, userid);
544 if (user == null) {
545 return 1; // 用户不存在
546 }
547 Appeal appeal = new Appeal();
548 appeal.appealid = java.util.UUID.randomUUID().toString();
549 appeal.appealuserid = userid;
550 appeal.content = content;
551 appeal.user = user; // 设置关联的用户
552 Path storageDir = Paths.get(config.APPEAL_STORAGE_DIR);
553 if (!Files.exists(storageDir)) {
554 Files.createDirectories(storageDir);
555 }
556 String filename = file.getName();
557 Path target = storageDir.resolve(appeal.appealid + "_" + filename);
558 Files.copy(file.toPath(), target, StandardCopyOption.REPLACE_EXISTING);
559 appeal.status = 0; // 初始状态为未处理
560 appeal.fileURL = target.toString(); // 设置文件存储路径
561 entityManager.getTransaction().begin();
562 entityManager.persist(appeal);
563 entityManager.getTransaction().commit();
564 return 0; // 成功提交申诉
565 } catch (Exception e) {
566 e.printStackTrace();
567 if (entityManager.getTransaction().isActive()) {
568 entityManager.getTransaction().rollback();
569 }
570 return -1; // 出现异常
571 } finally {
572 if (entityManager != null){
573 entityManager.close();
574 }
575 }
576 }
Raverf79fdb62025-06-03 06:02:49 +0000577}