Open Jacobvu84 opened 2 years ago
@Autowired đây là một DI = Dependency Injection. Giúp khởi tạo một đối tượng ngay từ khi application bắt đầu và sử dụng nó cho cả chương trình. Giống với khái niệm Singleton pattern
Cũ
package jacob.vu.coffee.controllers;
....
@RestController
@RequestMapping(path = "/api/v1/products")
public class ProductController {
@GetMapping("")
List<Product> getAllProducts(){
return List.of(
new Product(1L, "Iphone 14", 2022, 800.0, ""),
new Product(2L, "VSmart Pro", 2021, 900.0, ""));
}
}
Mới
@RestController
@RequestMapping(path = "/api/v1/products")
public class ProductController {
@Autowired
ProductRepository repository;
@GetMapping("")
List<Product> getAllProducts(){
return repository.findAll();
}
}
Vậy repository.findAll();
sẽ lấy dữ liệu ở đâu ?
@Configuration
class nào sử dụng annotation này thì bên trong sẽ chứa những Bean method những bean methods này sẽ được gọi ngay khi application run.
Chúng ta có thể dụng những @Bean
này để khởi tạo database, biến môi trường.
package jacob.vu.coffee.database;
import jacob.vu.coffee.models.Product;
import jacob.vu.coffee.repositories.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Database {
private static final Logger logger = LoggerFactory.getLogger(Database.class);
@Bean
CommandLineRunner initDatabase(ProductRepository productRepository){
return new CommandLineRunner() {
@Override
public void run(String... args) throws Exception {
Product productA = new Product(1L, "Iphone 14", 2022, 800.0, "");
Product productB = new Product(2L, "VSmart Pro", 2021, 900.0, "");
logger.info("insert database" + productRepository.save(productA));
logger.info("insert database" + productRepository.save(productB));
}
};
}
}
[Issue]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productRepository' defined in jacob.vu.coffee.repositories.ProductRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class jacob.vu.coffee.models.Product
Not a managed type: class jacob.vu.coffee.models.Product
Lỗi liên quan đến Jpa. Khi @Bean
hoạt động thì nó không tìm thấy thực thể
Product.
[Fix]
Sử dụng @Entity
cho Product
class
Khi sử dụng @Entity
thì nó yêu cầu Product phải có primary key. Ta cần phải chọn một trường làm khóa chính cho entity này.
Sử dụng @Id
để đánh chọn.
Nếu muốn giá trị id tự động tăng thì dùng @GeneratedValue(strategy = GenerationType.AUTO)
...
@Entity
public class Product {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
private String productName;
private int year;
.....
[Issue]
GenerationTarget encountered exception accepting command : Error executing DDL "create table product (product_id bigint not null, price double, product_name varchar(255), url varchar(255), year integer not null, primary key (product_id))" via JDBC Statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "create table product (product_id bigint not null, price double, product_name varchar(255), url varchar(255), [*]year integer not null, primary key (product_id))"; expected "identifier"; SQL statement: create table product (product_id bigint not null, price double, product_name varchar(255), url varchar(255), year integer not null, primary key (product_id)) [42001-214]
[Fix] Do trong Entity có chứa từ khóa của SQL
Tham khảo ở đây.
In my case, the attribute year
is reserved word for SQL
reserved for: dành riêng cho. Giữ chỗ
@Entity : This tells Hibernate to make a table out of this class
Repository là nơi chứa dữ liệu, dữ liệu sẽ được lấy ra từ đây để xử lý, nó chứa sẵn các hàm xử lý data như findAll, FindByXXXX, CRUD.... mà không cần phải viết lại. (Lợi của dùng framework là vậy. ko cần phải viết lại mọi thứ từ đầu)