---
# System prepended metadata

title: 存取資料庫資料
tags: [Spring  MVC]

---

---
tags: Spring  MVC
---
# 存取資料庫資料
Spring鼓勵藉由介面而不透過類別寫程式，讓程式更加彈性。
因此準備Service介面、Service、DAO介面、DAO以及Controller進行控制(前提，必須準備好bean，如Bookbeab、CompanyBean、MemberBean)



## Service介面(把所有要做的方法列出來):

```
public interface ProductService {

	List<BookBean> getAllProduct();
	
	void updateAllStocks();
	
	List<String> getAllCategories();
	
	List<BookBean> getProductByCategory(String category);
	
	public BookBean getProductById(int productId);
	
	void  addProduct(BookBean product);
	
	CompanyBean  getCompanyById(int companyId);
	
	List<CompanyBean>  getCompanyList();
}
```

## Service.java

1. 註釋@Service
2. 要宣告session工廠，並透過@Autowired建構子注入
3. 每個方法都是一個交易，因此要註釋@Transactional，代表方法執行時，會自動開交易，結束會自動關交易，有錯誤會自動rollback
```
@Service
public class ProductServiceImpl implements ProductService {

	SessionFactory factory;
	ProductDao productDao;//這是ProductDao 介面，不是類別(也就是對介面操作，不要對類別操作)
	
	
	@Autowired
	public ProductServiceImpl(SessionFactory factory, ProductDao productDao) {
		this.factory = factory;
		this.productDao = productDao;
	}

/*
	@Transactional
	@Override
	public List<BookBean> getAllProduct() {
		Session session = factory.getCurrentSession();
		Transaction tx=null;
		List<BookBean> list=null;
		try {
			tx=session.beginTransaction();
			list = productDao.getAllProduct();
			tx.commit();
		} catch (Exception e) {
			if(tx!=null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		}
		return list;
	}
 */
	
	
	//select All Product
	@Transactional
	@Override
	public List<BookBean> getAllProduct() {
		List<BookBean> list=productDao.getAllProduct();
		return list;
	
	}

	//update By Id
	@Transactional
	@Override
	public void updateAllStocks() {
	    List<BookBean> allProducts = productDao.getAllProduct();
	    for(BookBean bb : allProducts) {
	        if (bb.getStock() != null && bb.getStock() < 50) {
	        	productDao.updateStock(bb.getBookId(), bb.getStock() + 50);
	        }
	    }
	}

	//select All Categories
	@Transactional
	@Override
	public List<String> getAllCategories() {
		// TODO Auto-generated method stub
		return productDao.getAllCategories();
	}

	
	//select by Category
	@Transactional
	@Override
	public List<BookBean> getProductByCategory(String category) {
		// TODO Auto-generated method stub
		return productDao.getProductByCategory(category);
	}

	//select Product By Id
	@Transactional
	@Override
	public BookBean getProductById(int productId) {
		
		return productDao.getProductById(productId);
	}
	
	//Insert Product
	@Transactional
	@Override
	public void addProduct(BookBean product) {
		// TODO Auto-generated method stub
		productDao.addProduct(product);
	}
	
	//select company by id
	@Transactional
	@Override
	public CompanyBean getCompanyById(int companyId) {
		// TODO Auto-generated method stub
		return productDao.getCompanyById(companyId);
	}
	
	// select All company
	@Transactional
	@Override
	public List<CompanyBean> getCompanyList() {
		// TODO Auto-generated method stub
		return productDao.getCompanyList();
	}

}
```


## DAO介面(把所有要做的方法列出來):
```
public interface ProductDao {

	//介面把所有要做的方法列出來
	
	List<BookBean> getAllProduct();
	
	void updateStock(int productId,int newQuantity);
	
	List<String> getAllCategories();
	
	List<BookBean> getProductByCategory(String category);
	
	public BookBean getProductById(int productId);
	
	
	void  addProduct(BookBean product);
	
	CompanyBean  getCompanyById(int companyId);
	
	List<CompanyBean>  getCompanyList();
}
```

## DAO:
1. 註釋@Repository
2. 要宣告session工廠，並透過@Autowired建構子注入

```
@Repository
public class ProductDaoImpl implements ProductDao {
	SessionFactory factory;
	// RootAppConfig.java已經註冊了，所以直接透過下面的建構子@Autowired

	@Autowired
	public ProductDaoImpl(SessionFactory factory) {
		this.factory = factory;
	}

//select All
	@Override
	public List<BookBean> getAllProduct() {
		Session session = factory.getCurrentSession();
		String hql = "FROM BookBean";
		List<BookBean> resultList = session.createQuery(hql, BookBean.class).getResultList();
		return resultList;
	}

//update By Id
	@Override
	public void updateStock(int productId, int newQuantity) {
		Session session = factory.getCurrentSession();
		String hql = "UPDATE BookBean bb SET bb.stock= :qty WHERE bb.bookId = :id";
		session.createQuery(hql).setParameter("qty", newQuantity).setParameter("id", productId).executeUpdate();
	}

//select All Categories
	@Override
	public List<String> getAllCategories() {
		Session session = factory.getCurrentSession();
		String hql = "SELECT DISTINCT bb.category FROM BookBean bb";
		return session.createQuery(hql, String.class).getResultList();
	}

//select by Category
	@Override
	public List<BookBean> getProductByCategory(String category) {
		Session session = factory.getCurrentSession();
		String hql = "FROM BookBean bb WHERE bb.category = :cate";
		return session.createQuery(hql, BookBean.class).setParameter("cate", category).getResultList();
	}

//select Product By Id
	@Override
	public BookBean getProductById(int productId) {
		Session session = factory.getCurrentSession();
		BookBean bb = session.get(BookBean.class, productId);
		if (bb == null) {
			throw new ProductNotFoundException("產品編號：" + productId + "找不到", productId);
		}
		return bb;
	}

//Insert Product
	@Override
	public void addProduct(BookBean product) {
		Session session = factory.getCurrentSession();
		CompanyBean cb = getCompanyById(product.getCompanyId());
		product.setCompanyBean(cb);
		session.save(product);
	}

//select company by id
	@Override
	public CompanyBean getCompanyById(int companyId) {

		Session session = factory.getCurrentSession();
		CompanyBean cb = session.get(CompanyBean.class, companyId);
		return cb;
	}

	// select All company
	@Override
	public List<CompanyBean> getCompanyList() {
		Session session = factory.getCurrentSession();
		String hql = "FROM CompanyBean";
		List<CompanyBean> list = session.createQuery(hql, CompanyBean.class).getResultList();
		return list;
	}

}
```


## Controller
1. 註釋@Controller
2. 要宣告session工廠，並透過@Autowired建構子注入

```
@Controller
public class ProductController {

	
	ProductService productService;
    ServletContext servletContext;//後面抓圖片要用的
    
    @Autowired
	public ProductController(ProductService productService, ServletContext servletContext) {
		this.productService = productService;
		this.servletContext = servletContext;
	}
    
    @GetMapping("/products")
	public String list(Model model) {
		
		List<BookBean> beans = productService.getAllProduct();
		model.addAttribute("products",beans);
		
		return "products";	
		
	}
    //後面可以有更多請求
    
    }
```
架構
DAO處理資料庫相關功能
Service除了資料庫相關方法(所以import DAO介面操作)，還有商業邏輯的方法。
Control透過Service進行方法執行
![](https://i.imgur.com/Qx98KEG.png)