Practical Techniques for Java Business Development
Window Management Shortcuts
Minimize all open windows with Caps Lock + Win + m, restore minimized windows with Shift + Win + m. Use Ctrl + Shift + U to toggle the case of selected text.
MyBatis-Plus Best Practices
Prefer database-side queries over Java Stream operations for improved performance. Common usage examples:
// Single record query
BizDetails detail = lambdaQuery().eq(BizDetails::getId, recordId).one();
// Update via LambdaUpdateWrapper
LambdaUpdateWrapper<ExportLog> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(ExportLog::getUpdateTime, LocalDateTime.now())
.eq(ExportLog::getId, targetId);
update(updateWrapper);
// Alternative update approach
TreeVO treeEntity = BeanUtil.copyProperties(sourceTree, TreeVO.class);
update(treeEntity, new LambdaUpdateWrapper<TreeVO>()
.eq(TreeVO::getId, sourceTree.getId()));
Common Query Examples
public List<DetailVO> getDetailedData(String searchKeyword, LocalDate startDate, LocalDate endDate) {
LambdaQueryWrapper<Detail> queryWrapper = new LambdaQueryWrapper<>();
// Fuzzy match on multiple fields if search keyword is present
if (StringUtils.isNotBlank(searchKeyword)) {
queryWrapper.and(w -> w.like(Detail::getRole, searchKeyword)
.or().like(Detail::getRevenue, searchKeyword)
.or().like(Detail::getExpense, searchKeyword));
}
// Filter by start date
if (Objects.nonNull(startDate)) {
LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
queryWrapper.ge(Detail::getCreateTime, startDateTime);
}
// Filter by end date
if (Objects.nonNull(endDate)) {
LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
queryWrapper.le(Detail::getCreateTime, endDateTime);
}
List<Detail> detailList = list(queryWrapper);
return BeanUtil.copyToList(detailList, DetailVO.class);
}
Note: Add the generic type marker static <T> when using generic parameters, and use and() for LIKE conditions while other conditions do not require it.
Nullable Request Parameters
Use required = false to mark request parmaeters as optional:
@RequestParam(value = "floorNumber", required = false) String searchKeyword
String and Object Null Checks
// Check null for any type: collection, object, field
ObjectUtil.isEmpty(dto.getId())
// Safe string equality check
Objects.equals(firstValue, secondValue)
// Optional null handling
String sellerId = Optional.ofNullable(response.getSellerId()).orElse(StringUtils.EMPTY);
// Equivalent traditional check
String existingId = response.getSellerId();
return existingId != null ? existingId : StringUtils.EMPTY;
Entity Fields Without DTOs
Use the @TableField(exist = false) annotation to mark entity fields that do not exist in the database table, eliminating the need to create a separate DTO for temporary fields.
Database Table Design
Recommended standard columns for audit tracking:
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'Record creation time',
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Record update time'
Tree Structure Database and Frontend Implemantation
Collecsion Fuzzy Search
public List<EquipmentVO> filterEquipmentList(List<EquipmentVO> sourceList, String wasteType, String equipmentName) {
String trimmedWasteType = StringUtils.trimToEmpty(wasteType);
String trimmedEquipmentName = StringUtils.trimToEmpty(equipmentName);
// Return full list if both filters are empty
if (StringUtils.isEmpty(trimmedWasteType) && StringUtils.isEmpty(trimmedEquipmentName)) {
return sourceList;
}
// Apply fuzzy filtering via stream
return sourceList.stream()
.filter(item -> (StringUtils.isEmpty(trimmedWasteType) || item.getWasteType().contains(trimmedWasteType))
&& (StringUtils.isEmpty(trimmedEquipmentName) || item.getEquipmentName().contains(trimmedEquipmentName)))
.collect(Collectors.toList());
}
Unique ID Generation
package com.company.fishery.utils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Generates unique IDs using current timestamp plus 4-digit incremental sequence
*/
public class UniqueIdGenerator {
private static final AtomicInteger sequenceCounter = new AtomicInteger(0);
public static synchronized Long generateUniqueSequenceId() {
long timestamp = System.currentTimeMillis();
int currentSequence = sequenceCounter.incrementAndGet();
// Ensure sequence is 4 digits, pad with leading zeros if needed
String sequenceStr = String.format("%04d", currentSequence);
return Long.parseLong(timestamp + sequenceStr);
}
}
Execution Time Calculation
long startTimestamp = System.currentTimeMillis();
// Your business logic here
long endTimestamp = System.currentTimeMillis();
long elapsedTime = endTimestamp - startTimestamp;
LOG.info("Business logic execution time: {} ms", elapsedTime);
Current Time Formatting
// Format local date to Chinese style
LocalDate currentDate = LocalDate.now();
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String formattedDate = currentDate.format(dateFormatter);
System.out.println(formattedDate);
// Format local datetime to standard format
LocalDateTime currentDateTime = LocalDateTime.now();
DateTimeFormatter datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDatetime = currentDateTime.format(datetimeFormatter);
MPJ Multi-table Queries
public List<AccountBalanceVO> getBalanceList(String searchKeyword) {
MPJLambdaWrapper<AccountBalance> queryWrapper = new MPJLambdaWrapper<>()
.selectAll(AccountBalance.class)
.select(FinancialRecord::getExpenseAmount)
.select(FinancialRecord::getExpenseName)
.select(FinancialRecord::getIncomeAmount)
.select(FinancialRecord::getIncomeName)
.select(FinancialRecord::getRecordTime)
.leftJoin(FinancialRecord.class, FinancialRecord::getBalanceId, AccountBalance::getId);
String trimmedKeyword = StringUtils.trimToEmpty(searchKeyword);
if (StringUtils.isNotBlank(trimmedKeyword)) {
queryWrapper.and(w -> w.like(FinancialRecord::getExpenseAmount, trimmedKeyword)
.or().like(FinancialRecord::getExpenseName, trimmedKeyword)
.or().like(FinancialRecord::getIncomeAmount, trimmedKeyword)
.or().like(FinancialRecord::getIncomeName, trimmedKeyword)
.or().like(FinancialRecord::getRecordTime, trimmedKeyword));
}
return baseMapper.selectJoinList(AccountBalanceVO.class, queryWrapper);
}
Transaction Management
return transactionTemplate.execute(status -> {
configService.updateConfigValue(SysConfigConstants.SPLASH_AD_SWITCH, adSwitchStatus);
configService.updateConfigValue(SysConfigConstants.SPLASH_AD_SHOW_DURATION, config.getShowDuration().toString());
configService.updateConfigValue(SysConfigConstants.SPLASH_AD_REFRESH_INTERVAL, config.getRefreshInterval().toString());
if (CollUtil.isEmpty(finalAdConfigList)) {
adGroupService.deleteByTagAndMerchantId(AdGroupConstants.TAG_SPLASH_AD, 0);
} else {
adGroupService.batchSave(finalAdConfigList);
}
return Boolean.TRUE;
});
Remote API Calls
String jsonPayload = JsonUtil.toJsonString(requestBody);
String responseBody = HttpUtil.createPost(apiUrl)
.header("Content-Type", "application/json;charset=UTF-8")
.body(jsonPayload)
.timeout(20000)
.execute()
.body();
Database Stored String to Frontend JSON Field
// Non-database entity field for JSON list
@TableField(exist = false)
private List<String> securityLevelList;
// Read from database and convert to list
String jsonStr = entity.getSecurityLevel().replace("'", "\"");
List<String> levels = JSON.parseArray(jsonStr, String.class);
entity.setSecurityLevelList(levels);
// Save list to database as quoted string
metadata.setSecurityLevel(JSON.toJSONString(metadata.getSecurityLevelList()).replace("\"", "'"));
// Frontend request example
"securityLevelList": ["Public", "Internal", "Sensitive", "Confidential", "Top Secret"]
Expired Token Refresh and Remote Login
/**
* Refresh expired token automatically
*/
protected String executeWithTokenRetry(HttpRequest originalRequest) {
try (HttpResponse firstResponse = originalRequest.execute()) {
String responseBody = firstResponse.body();
try {
JsonNode responseJson = JsonUtil.parseToJsonNode(responseBody);
if (responseJson.get("code") != null) {
// Re-login to get new token
loginToFastGpt();
// Update request header with new token
originalRequest.header("Authorization", "Bearer " + getCurrentToken());
// Retry the original request
try (HttpResponse retryResponse = originalRequest.execute()) {
return retryResponse.body();
} catch (Exception retryEx) {
LOG.debug("Retry request failed", retryEx);
}
}
return responseBody;
} catch (JsonProcessingException jsonEx) {
LOG.debug("Failed to parse response body: {}", responseBody, jsonEx);
}
} catch (Exception requestEx) {
LOG.debug("Initial request failed", requestEx);
}
return "{}";
}
/**
* Login to FastGPT to retrieve access token
*/
private void loginToFastGpt() {
FastGptLoginRequest loginRequest = new FastGptLoginRequest();
loginRequest.setUsername(fastGptConfig.getAccount());
loginRequest.setPassword(DigestUtil.sha256Hex(fastGptConfig.getPassword()));
String loginJson = JsonUtil.toJsonString(loginRequest);
String loginApi = fastGptConfig.getHost() + fastGptConfig.getLoginEndpoint();
HttpResponse loginResponse = HttpUtil.createPost(loginApi)
.header("Content-Type", "application/json")
.body(loginJson)
.execute();
JsonNode loginJsonNode = JsonUtil.parseToJsonNode(loginResponse.body());
JsonNode loginData = loginJsonNode.get("data");
String newToken = loginData.get("token").asText();
setCurrentToken(newToken);
}
private String currentToken;
public String getCurrentToken() {
if (StringUtils.isEmpty(currentToken)) {
loginToFastGpt();
}
return currentToken;
}
public void setCurrentToken(String token) {
this.currentToken = token;
}
Recommended Development Plugins
- Show Comment: Display inline comment previews for easier code reading
- Rainbow Brackets: Colorize matching brackets to improve code readability, use
Ctrl+Right ClickorAlt+Right Clickto select code blocks - Find interface implementations via the IDE's
Viewmenu - Configure fallback font: Go to
Settings > Appearance & Behavior > Appearance > Font > Fallback fontand set toSimHeifor better Chinese character rendering