11 Common Questions about Java and Spring Fundamentals (Part 2)
Reading from previous article: 10 Common Questions about Java Fundamentals (Part 1)
11. SOLID
The SOLID principles are a set of five design principles that are widely used in object-oriented programming to create scalable, maintainable, and flexible software
- Single Responsibility Principle (SRP): a class should have a single responsibility or purpose. This helps to keep the class focused, easy to understand, and makes it less likely to be affected by changes in other parts of the codebase.
- Open/Closed Principle (OCP): This principle states that software entities should be open for extension but closed for modification. It encourages developers to design classes in a way that allows new function to be added without modifying existing code. This can be achieved through the use of inheritance, interfaces, and dependency injection.
- Liskov Substitution Principle (LSP): This principle is about maintaining substitutability of derived classes for their base classes. In simple terms, objects of a base class should be replaceable with objects of a derived class without affecting the correctness of the program. This ensures that subclasses adhere to the behavior expected of their base classes.
- Interface Segregation Principle (ISP): Instead of using one large interface, we should split it into many small interfaces, with many specific purposes
- Dependency Inversion Principle (DIP):
- High-level modules should not depend on low-level modules. Both should depend on abstraction.
- Interface (abstraction) should not depend on details, instead, details should depend on abstractions. (It means classes communicate with each other through interfaces, not through implementation method.)
This promotes loose coupling and makes the codebase more flexible and easier to maintain.
12. Transaction
Transactions ensure that a group of database operations are executed as a single unit of work, either all succeeding or nothing at all, thus maintaining data integrity and consistency.
The rollbackFor
parameter specifies the types of exceptions for which the transaction should be rolled back
13. @Autowrite in Spring Boot
In Spring Boot, @Autowired is a commonly used annotation that is part of the Spring Framework’s Dependency Injection (DI) mechanism. It is used to auto inject dependencies into your Spring managed beans (e.g., Spring components, services, controllers) without the need for manual wiring. This helps to promote loose coupling between components and simplifies the configuration process.
When you annotate a field, constructor, or a method with @Autowired, Spring will automatically resolve and provide the appropriate dependency at runtime. It looks for a matching bean of the required type in the application context and injects it into the annotated component.
14. IOC in Spring
In Spring Boot, IOC mean “Inversion of Control” that guides how it’s designed. This IOC thing is a design pattern that helps keep things organized by controlling how a program runs through external setup instead of directly putting dependencies into the code. This way, we can create applications that are flexible and easier to maintain.
In Spring Boot, IOC is made possible by the Spring framework’s “dependency injection” feature. The Spring container, also known as the application context, handles the creation and connections of objects (which are called “beans”) and their dependencies. So, Spring Boot takes care of managing how things work together behind the scenes, making development smoother and more organized.
15. Singleton Pattern
The Singleton Pattern is a creational design pattern used to ensure that a class has only one instance and provides a global point of access to that instance. This pattern is useful when you want to restrict the create a class to a single object that serves as a shared resource across the application.
Thread Safe in Singleton Pattern:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
// Initialization code (if any)
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Double-Checked Locking (Lazy Initialization with double-check):
To improve performance, you can use the double-checked locking pattern, which reduces the overhead of synchronization after the instance has been created.
The volatile
keyword ensures that the instance variable is correctly handled by the JVM across threads, and the double-checked locking pattern ensures that only one thread creates the instance.
16. Bean in Spring boot
In Spring Boot, a bean is a term used to describe a managed object instance and managed by the Spring IoC (Inversion of Control) container. These beans are the fundamental building blocks of a Spring application, and the Spring IoC container is responsible for creating and managing them based on their configurations.
To define a bean in Spring Boot, you can use the @Bean annotation on a method within a configuration class.
17. Indexing in Database
Indexing in a database is a technique used to improve the performance of data retrieval operations. It involves creating special data structures, known as indexes, that provide faster access to specific rows within a table.
18. Types indexing in Database
18.1. B-tree Index
B+ trees are commonly used for creating indexes in databases due to their balanced structure and ability to efficiently handle range queries.
- They are well-suited for various data types and support equality and range queries efficiently.
- B-tree indexes maintain the data in a balanced tree structure, allowing for fast lookup, insertion, and deletion operations.
- Suitable for columns that have a high number of distinct values.
- Btree index is used in comparison expressions of the form: =, >, >=, <, <=, BETWEEN, LIKE.
18.2. Hash Index
- Index data is organized in the form of Key — Value linked together.
- Hash indexes are useful for exact match (equality) queries on columns with simple data types, like integers and character strings.
- They use a hash function to map the indexed column values to a fixed number of buckets, allowing for fast access to data.
- Hash indexes are not well-suited for range queries or non-equality operations.
- BTree index is used in comparison expressions of the form: = or <>
Example for indexing:
index(a,b,c)
where b = '' and c=''; —> will not use index
where a= '' and c = '' —> will use index
So if you index multiple columns, the most important thing is to search in the order the columns are indexed and make sure that the first column to be indexed will always be in your search criteria.
19. FetchType in Hibernate
FetchType is an enumerated type in the Java Persistence API (JPA) that specifies whether the field or property should be lazily loaded or eagerly loaded.
You can specify the fetch type of an association by using the fetch attribute of the @OneToMany, @ManyToOne, @OneToOne, or @ManyToMany annotations.
EAGER: When FetchType.EAGER is specified, the associated entity is fetched from the database immediately along with the parent entity. This means that whenever the parent entity is loaded or fetched, the associated entity will also be fetched in the same query. EAGER loading is suitable when you often need to access the associated entity, and its data is frequently required during normal business logic.
LAZY: When FetchType.LAZY is specified, the associated entity is not fetched immediately when loading the parent entity. Instead, it will be loaded from the database only when the associated entity is accessed or referenced for the first time. This can help avoid unnecessary database queries and improve performance when the associated entity is not always needed during regular processing.
20. Distributed Transaction in Database
A distributed transaction in a database refers to a transaction that involves multiple separate databases or data stores located in different physical locations or on different servers. The primary goal of distributed transactions is to ensure that a set of related operations across these distributed databases either succeed as a whole or fail completely, adhering to the principles of ACID (Atomicity, Consistency, Isolation, Durability) properties.
In a distributed transaction, all participating databases must either commit the transaction successfully or abort it entirely. This ensures data integrity and consistency across the distributed systems, even if some part of the transaction fails or encounters an error.
In micro-services we SAGA pattern
21. Design pattern in Java
A design patterns are solution for resolving a problem/task. There are 3 main categories abount Design Pattern in java that I know:
- Creational Pattern: Singleton Pattern, Builder Pattern, Factory Method Pattern, etc…
- Structural Pattern: Adapter Pattern, Bridge Pattern, Proxy Pattern, etc…
- Behavioral Pattern: Command Patern, Observer Pattern, State Pattern, etc…
Advantage of Design pattern:
- Reusable in multi projects.
- Provide a solution that help to define the system architecture.
- Provide transparency to design of an application and clairy to build system better.
Singleton Pattern ensures that a class has only one instance while providing a global access point to this instance. Singleton Pattern is mostly used on multi-threaded or database applications. It is used for logging, caching, thread pool, configuration settings, etc…
Advantage of Singleton Pattern is save memory because object is not created at each request, they is reused again and again.
Builder Pattern: help construct complex objects step by step. The pattern allows you to produce difference types and representations of an object using the same construction code.
Factory Method Pattern provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Adapter Pattern says that just converts the interface of a class into another interface that a client wants. The adapter pattern is also known as Wrapper.
Observer Pattern says that define a one-to-one dependency so that when one object changes state, all its dependents are notified and updated automatically. The Observer pattern is known as Publish — Subscribe model.