- Java is tough, sometimes
- Packages:
- Always lower case
- Package names should be unique
- Use your internet domain name, reversed, as a prefix for the package name
- Domain name components that are Java keywords should have that component start with an underscore
- Classes:
- PascalCase
- Class names should be nouns (they represend things)
- Should start with a capital letter
- Each word in the name should also start with a capital (LinkedList...)
- Interfaces
- PascalCase
- Should start with a capital letter
- Consider what object implementing the interface will become of what they will be able to do
- Methods
- camelCase
- often verb
- reflect the function performed or the result returned
- Constants
- ALL UPPER_CASE
- "final" keyword
- Variables:
A JavaBean is just a standard. It is a regular Java class, except it follows certain conventions:
- All properties are private
- Public getters/setters
- A public no-argument constructor (public all-argument constructor, optional)
- Implements Serializable.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {
private int age;
private String name;
}
- The 'beans' of JavaBeans are classes that encapsulate one or more objects into a single standardized object (the bean). This standardization allows the beans to be handled in a more generic fashion, allowing easier code reuse and introspection
- What is POJO?
- Can't Extend anything
- Can't Implement anything
- No outside annotaion
public class Cat {
int age;
String name;
}
- Not a POJO!
public class Cat implements Animals {
int age;
String name;
@Override
public void run(){
System.out.println(String.format("%s can be run", this.name));
}
}
- I prefer using record (java 16+) for visualize the DTO
public record SubcategoryDTO(
@NotNull(message = "Category id is required") @JsonProperty("category_id") Long categoryId,
@NotEmpty(message = "Sub Category name is required") Set<String> name
) {}
@JsonPropertyOrder({
"id",
"name",
"created_at",
"updated_at"
})
public record CategoryResponse(
Long id,
String name,
TreeSet<Subcategory> subcategories,
@JsonIgnore @JsonProperty("created_at") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS") LocalDateTime createdAt,
@JsonIgnore @JsonProperty("updated_at") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS") LocalDateTime updatedAt
) {}
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "categories")
public class Category extends BaseEntity {
@Id
@SequenceGenerator(name = "categories_seq", sequenceName = "categories_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "categories_seq")
@Column(name="id", unique=true, nullable=false)
@JsonProperty("id")
private Long id;
private String name;
@OneToMany(mappedBy = "category")
private Set<Subcategory> subcategories;
}
@PostMapping("/sub")
@PreAuthorize("hasRole('ROLE_MANAGER')")
public ResponseEntity<ApiResponse<CreateNewSubcategoryResponse>> createSubCategory(
@Valid @RequestBody SubcategoryDTO subcategoryDTO,
BindingResult result
) {
if (result.hasErrors()) {
throw new MethodArgumentNotValidException(result);
}
return ResponseEntity.status(HttpStatus.CREATED).body(
ApiResponse.<CreateNewSubcategoryResponse>builder()
.message("Create sub category successfully")
.statusCode(HttpStatus.CREATED.value())
.isSuccess(true)
.data(categoryService.createSubCategory(subcategoryDTO))
.build()
);
}
@Override
public CreateNewSubcategoryResponse createSubCategory(SubcategoryDTO subcategoryDTO)
throws DataNotFoundException, DataAlreadyExistException {
Category category = categoryRepository.findById(subcategoryDTO.categoryId())
.orElseThrow(() -> new CategoryNotFoundException("Category not found"));
if (subcategoryRepository.existsByCategoryIdAndNameIn(category.getId(), subcategoryDTO.name())) {
throw new DataAlreadyExistException("Subcategory already exist in category: " + category.getId());
}
subcategoryDTO.name().forEach(name -> {
subcategoryRepository.save(
Subcategory.builder()
.name(name)
.category(category)
.build());
});
return new CreateNewSubcategoryResponse(categoryMapper.toCategoryResponse(category));
}