使用IntelliJ IDEA開發SpringMVC網站(三)資料庫配置
六、資料庫配置
下面,就要通過一個簡單的例子,來介紹SpringMVC如何整合Spring Data JPA(由 Hibernate JPA 提供),來進行強大的資料庫訪問,並通過本章節的講解,更加深刻地認識Controller是如何進行請求處理的,相信看完這一章節,你就可以開始你的開發工作了。
準備工作:
在src\main\java中新建兩個包:com.gaussic.model、com.gaussic.repository,將在後面用上,如下圖所示:
1、建立Mysql資料庫
本文的講解使用Mysql資料庫,如果使用其它資料庫的讀者,可以去網上參考其他的配置教程,在此不做太多的敘述。資料庫是一個底層的東西,底層的細節對上層的抽象並沒有太大的影響,因此,只要配置好資料庫,本章的內容仍然是適用於所有資料庫的(貌似如此)。
假設我們現在要建立一個小小的部落格系統,其資料庫ER圖如下所示(當然這只是一個小小的例子,真實的部落格系統比這要複雜的多):
新建一個數據庫springdemo,在資料庫中,有兩張表:
(1)使用者表user:使用者登入資訊,主鍵id設為自增;
(2)博文表blog:儲存使用者發表的博文,主鍵id設為自增,其中有一個外來鍵user_id連結到user表。
詳細表結構如下圖所示:
使用MySQL Workbench新增外來鍵流程:
注意:在新增外來鍵時,應該根據需求設定,例如右邊紅框中的Foreign Key Options,預設在Delete時是NO ACTION,說明在刪除一個使用者時,如果資料庫中存在該使用者的文章,那麼就無法刪除該使用者,也無法刪除該使用者的所有文章,而如果將該選項改為CASCADE,那麼刪除該使用者,就會同時刪除該使用者所有的文章。通常後者是不太可取的,因為如果發生了刪除使用者的誤操作,很有可能該使用者的內容被連帶刪除,且不可逆,這也是實現真實系統時需要考慮的原因之一。
2、IntelliJ IDEA匯入資料庫
對於此前所接觸的一些常用的框架中,一張資料表往往對應一個Java Bean。在SpringMVC中,這個Java Bean相當於model。那麼,這個類是否需要自己來寫呢?不需要,利用IntelliJ IDEA可以幫我們自動的生成這些JavaBean。
首先,右鍵專案,選擇Add Framework Support:
下拉選擇JavaEE Persistence,右邊provider選擇Hibernate:
注:這一部分有一點過時,更新的專案中直接把資料庫的配置放在了mvc-dispatcher-servlet.xml中,但依然要做這一步的操作,為了這一步可以使用Persistence的工具。
關於新的配置,可以翻到部落格底部。
在這一步結束後,我們可以發現,在resources裡面生成了persistence.xml配置檔案,左邊欄出現了一個Persistence標題(若沒有請點選左下角那個灰框):
persistemce.xml具體如下:
<?xml version="1.0" encoding="UTF-8"?>
<persistencexmlns="http://java.sun.com/xml/ns/persistence"version="2.0">
<persistence-unitname="NewPersistenceUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<propertyname="hibernate.connection.url"value=""/>
<propertyname="hibernate.connection.driver_class"value=""/>
<propertyname="hibernate.connection.username"value=""/>
<propertyname="hibernate.connection.password"value=""/>
<propertyname="hibernate.archive.autodetection"value="class"/>
<propertyname="hibernate.show_sql"value="true"/>
<propertyname="hibernate.format_sql"value="true"/>
<propertyname="hbm2ddl.auto"value="update"/>
</properties>
</persistence-unit>
</persistence>
我們先不著急填寫這個配置檔案。點開左邊欄的Persistence,顯示如下圖所示:
右鍵專案名,選擇Generate Persistence Mapping,再選擇By Database Schema:
出現如下介面,其主要需要配置的地方如下圖紅框所示:
點選Choose Data Source右邊的三個點選擇資料來源,在彈出的介面左上角選擇“+”,選擇Mysql:
在如下介面填寫主機、埠號、資料庫名、使用者名稱、密碼,如果驅動丟失點選下面的Download可以下載驅動,點選 Test Connection可以測試資料庫是否連線成功:
在以上介面配置完成後,點OK,第一次使用需要Setup Master Password:
回到如下頁面,package填寫model包(1),勾選Prefer primitive type使用原始資料型別(2),勾選Show default relationships以顯示所有資料庫關係(3),再點選重新整理按鈕(4),將會找到資料庫中的兩個表,勾選兩個資料表(5),再勾選Generate Column Defination以生成每一列的描述資訊(6)。選中blog表然後點選“+”號按鈕,新增外來鍵關係(7)。
點選OK後,在Database Schema Mapping中可以發現多出了兩個關係,如圖所示:
再點選OK,稍後,開啟model包,可以看到生成了兩個Java Bean,在SpringMVC中稱為兩個實體,它們對應了資料庫的兩張表:
BlogEntity如下所示(注意把java.sql.Date改為java.util.Date):
package com.gaussic.model;
import javax.persistence.*;
import java.util.Date;
/**
* Created by dzkan on 2016/3/8.
*/
@Entity
@Table(name = "blog", schema = "springdemo", catalog = "")
public classBlogEntity{
private int id;
private String title;
private String content;
private Date pubDate;
private UserEntity userByUserId;
@Id
@Column(name = "id", nullable = false)
publicintgetId(){
return id;
}
publicvoidsetId(int id){
this.id = id;
}
@Basic
@Column(name = "title", nullable = false, length = 100)
public String getTitle(){
return title;
}
publicvoidsetTitle(String title){
this.title = title;
}
@Basic
@Column(name = "content", nullable = true, length = 255)
public String getContent(){
return content;
}
publicvoidsetContent(String content){
this.content = content;
}
@Basic
@Column(name = "pub_date", nullable = false)
public Date getPubDate(){
return pubDate;
}
publicvoidsetPubDate(Date pubDate){
this.pubDate = pubDate;
}
@Override
publicbooleanequals(Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BlogEntity that = (BlogEntity) o;
if (id != that.id) return false;
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (content != null ? !content.equals(that.content) : that.content != null) return false;
if (pubDate != null ? !pubDate.equals(that.pubDate) : that.pubDate != null) return false;
return true;
}
@Override
publicinthashCode(){
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (content != null ? content.hashCode() : 0);
result = 31 * result + (pubDate != null ? pubDate.hashCode() : 0);
return result;
}
@ManyToOne
@JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
public UserEntity getUserByUserId(){
return userByUserId;
}
publicvoidsetUserByUserId(UserEntity userByUserId){
this.userByUserId = userByUserId;
}
}
再看UserEntity:
package com.gaussic.model;
import javax.persistence.*;
import java.util.Collection;
/**
* Created by dzkan on 2016/3/8.
*/
@Entity
@Table(name = "user", schema = "springdemo", catalog = "")
public classUserEntity{
private int id;
private String nickname;
private String password;
private String firstName;
private String lastName;
private Collection<BlogEntity> blogsById;
@Id
@Column(name = "id", nullable = false)
publicintgetId(){
return id;
}
publicvoidsetId(int id){
this.id = id;
}
@Basic
@Column(name = "nickname", nullable = false, length = 45)
public String getNickname(){
return nickname;
}
publicvoidsetNickname(String nickname){
this.nickname = nickname;
}
@Basic
@Column(name = "password", nullable = false, length = 45)
public String getPassword(){
return password;
}
publicvoidsetPassword(String password){
this.password = password;
}
@Basic
@Column(name = "first_name", nullable = true, length = 45)
public String getFirstName(){
return firstName;
}
publicvoidsetFirstName(String firstName){
this.firstName = firstName;
}
@Basic
@Column(name = "last_name", nullable = true, length = 45)
public String getLastName(){
return lastName;
}
publicvoidsetLastName(String lastName){
this.lastName = lastName;
}
@Override
publicbooleanequals(Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserEntity that = (UserEntity) o;
if (id != that.id) return false;
if (nickname != null ? !nickname.equals(that.nickname) : that.nickname != null) return false;
if (password != null ? !password.equals(that.password) : that.password != null) return false;
if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false;
if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false;
return true;
}
@Override
publicinthashCode(){
int result = id;
result = 31 * result + (nickname != null ? nickname.hashCode() : 0);
result = 31 * result + (password != null ? password.hashCode() : 0);
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
@OneToMany(mappedBy = "userByUserId")
public Collection<BlogEntity> getBlogsById(){
return blogsById;
}
publicvoidsetBlogsById(Collection<BlogEntity> blogsById){
this.blogsById = blogsById;
}
}
3、配置資料庫
既然資料庫已經匯入了,那麼前期準備工作基本完成,還需要進行最終的配置。
首先,開啟mvc-dispatcher-servlet.xml,新增下列配置(如果某些地方報錯,請選中並按Alt + Insert補全配置):
<!-- 表示JPA Repository所在的包 -->
<jpa:repositoriesbase-package="com.gaussic.repository"/>
<!-- 連結到persistence.xml -->
<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<propertyname="persistenceUnitName"value="defaultPersistenceUnit"/>
</bean>
<!-- 事務管理 -->
<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="entityManagerFactory"/>
</bean>
<!-- 開啟事務管理註解 -->
<tx:annotation-driventransaction-manager="transactionManager"/>
講解:
(1) jpa:repositories:這一部分涉及到資料庫的介面,將在後面詳解;
(2)entityManagerFactory:實體管理器工廠,讀取persistence.xml配置;
(3)transactionManager:事務管理器,利用entityManager進行事務管理;
(4)tx:annotation-driven:開啟事務管理器的註解驅動,可以使用註解的方法操縱資料庫。
整體如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--指明 controller 所在包,並掃描其中的註解-->
<context:component-scanbase-package="com.gaussic.controller"/>
<!-- 靜態資源(js、image等)的訪問 -->
<mvc:default-servlet-handler/>
<!-- 開啟註解 -->
<mvc:annotation-driven/>
<!--ViewResolver 檢視解析器-->
<!--用於支援Servlet、JSP檢視解析-->
<beanid="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>
<propertyname="prefix"value="/WEB-INF/pages/"/>
<propertyname="suffix"value=".jsp"/>
</bean>
<!-- 表示JPA Repository所在的包 -->
<jpa:repositoriesbase-package="com.gaussic.repository"/>
<!-- 連結到persistence.xml -->
<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<propertyname="persistenceUnitName"value="defaultPersistenceUnit"/>
</bean>
<!-- 事務管理 -->
<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="entityManagerFactory"/>
</bean>
<!-- 開啟事務管理註解 -->
<tx:annotation-driventransaction-manager="transactionManager"/>
</beans>
下面,填充persistence.xml,將persistence-unit的name改為 defaultPersistenceUnit。在下面的檔案中,我添加了一些更為詳細的配置:
<?xml version="1.0" encoding="UTF-8"?>
<persistencexmlns="http://java.sun.com/xml/ns/persistence"version="2.0">
<persistence-unitname="defaultPersistenceUnit"transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!-- 使用MySQL方言 -->
<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5Dialect"/>
<!-- 資料庫連線的URL地址 -->
<propertyname="hibernate.connection.url"value="jdbc:mysql://localhost:3306/springdemo"/>
<!-- 資料庫連線的驅動 -->
<propertyname="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver"/>
<!-- 資料庫連線的使用者名稱 -->
<propertyname="hibernate.connection.username"value="root"/>
<!-- 資料庫連線的密碼 -->
<propertyname="hibernate.connection.password"value="111111"