Java EE 學習(7):IDEA + maven + spring 搭建 web(3)- 配置數據庫


參考: https://my.oschina.net/gaussik/blog/513444

注:在閱讀本文前,請先閱讀:

Java EE 學習(5):IDEA + maven + spring 搭建 web(1)

Java EE 學習(6):IDEA + maven + spring 搭建 web(2)

5 數據庫配置

下面,就要通過一個簡單的例子,來介紹 SpringMVC 如何集成 Spring Data JPA(由 Hibernate JPA 提供),來進行強大的數據庫訪問,並通過本章節的講解,更加深刻地認識 Controller 是如何進行請求處理的,看完這一章節,你就可以開始你的開發工作了。

准備工作:

    在src\main\java 中新建兩個包:com.example.model、com.example.repository,將在后面用上,如下圖所示:

(1)、創建Mysql數據庫

      本文的講解使用Mysql數據庫,如果使用其它數據庫的讀者,可以去網上參考其他的配置教程,在此不做太多的敘述。數據庫是一個底層的東西,底層的細節對上層的抽象並沒有太大的影響,因此,只要配置好數據庫,本章的內容仍然是適用於所有數據庫的(貌似如此)。

      假設我們現在要建立一個小小的博客系統,其數據庫ER圖如下所示(當然這只是一個小小的例子,真實的博客系統比這要復雜的多):

    新建一個數據庫springdemo,在數據庫中,有兩張表:

    (1)用戶表user:用戶登錄信息,主鍵 id 設為自增

    (2)博文表blog:儲存用戶發表的博文,主鍵 id 設為自增,其中有一個外鍵 user_id 鏈接到 user 表。

    詳細表結構如下圖所示:

使用MySQL Workbench添加外鍵流程:

注意:在添加外鍵時,應該根據需求設置,例如右邊紅框中的 Foreign Key Options,默認在 Delete 時是 NO ACTION,說明在刪除一個用戶時,如果數據庫中存在該用戶的文章,那么就無法刪除該用戶,也無法刪除該用戶的所有文章,而如果將該選項改為 CASCADE,那么刪除該用戶,就會同時刪除該用戶所有的文章。通常后者是不太可取的,因為如果發生了刪除用戶的誤操作,很有可能該用戶的內容被連帶刪除,且不可逆,這也是實現真實系統時需要考慮的原因之一。

 

以下是使用 Navicat for MySql 創建的過程:

user 表:

blog 表:

添加外鍵:

(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"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="NewPersistenceUnit">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.connection.url" value=""/>
            <property name="hibernate.connection.driver_class" value=""/>
            <property name="hibernate.connection.username" value=""/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="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:

    

    回到如下頁面:

    (1)package 填寫 model 包;

    (2) 勾選 Prefer primitive type 使用原始數據類型;

    (3) 勾選 Show default relationships 以顯示所有數據庫關系;

    (4)再點擊刷新按鈕,將會找到數據庫中的兩個表

   (5)勾選兩個數據表;

    (6) 再勾選 Generate Column Defination 以生成每一列的描述信息。

    (7)選中 blog 表然后點擊“+”號按鈕,添加外鍵關系(若已經添加過外鍵,此步則可以跳過)

 添加外鍵(若已經添加過,此不可忽略)

    點擊OK后,在Database Schema Mapping中可以發現多出了兩個關系,如圖所示:

   再點擊OK,稍后,打開model包,可以看到生成了兩個Java Bean,在SpringMVC中稱為兩個實體,它們對應了數據庫的兩張表:

BlogEntity 如下所示(注意把java.sql.Date改為java.util.Date):

package com.example.model;    # 注意自己的包名

import javax.persistence.*;
import java.util.Date;   # change: 更改導入包

/**
 * Created by dzkan on 2016/3/8.
 */
@Entity
@Table(name = "blog", schema = "springdemo", catalog = "")
public class BlogEntity {
    private int id;
    private String title;
    private String content;
    private Date pubDate;
    private UserEntity userByUserId;    

    @Id
    @Column(name = "id", nullable = false)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "title", nullable = false, length = 100)
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Basic
    @Column(name = "content", nullable = true, length = 255)
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Basic
    @Column(name = "pub_date", nullable = false)
    public Date getPubDate() {
        return pubDate;
    }

    public void setPubDate(Date pubDate) {
        this.pubDate = pubDate;
    }

    @Override
    public boolean equals(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
    public int hashCode() {
        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; } public void setUserByUserId(UserEntity userByUserId) { this.userByUserId = userByUserId; } }

# 此處,注意,對於 “blog” , “springdemo” 之類的標紅,不用管,是 IDEA 自身問題,不影響項目運行

再看UserEntity:

package com.example.model;   # 使用自己的包

import javax.persistence.*;
import java.util.Collection;  

/**
 * Created by dzkan on 2016/3/8.
 */
@Entity
@Table(name = "user", schema = "springdemo", catalog = "")
public class UserEntity {
    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)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "nickname", nullable = false, length = 45)
    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    @Basic
    @Column(name = "password", nullable = false, length = 45)
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Basic
    @Column(name = "first_name", nullable = true, length = 45)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Basic
    @Column(name = "last_name", nullable = true, length = 45)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public boolean equals(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
    public int hashCode() {
        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; } public void setBlogsById(Collection<BlogEntity> blogsById) { this.blogsById = blogsById; } }

(3)、配置數據庫

    既然數據庫已經導入了,那么前期准備工作基本完成,還需要進行最終的配置。

    首先,打開 mvc-dispatcher-servlet.xml,添加下列配置(如果某些地方報錯,請選中並按 Alt + Insert 補全配置):

<!-- 表示JPA Repository所在的包 -->
<jpa:repositories base-package="com.example.repository"/>   # 注意自己的包名

<!-- 鏈接到persistence.xml -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="defaultPersistenceUnit"/>
</bean>

<!-- 事務管理 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!-- 開啟事務管理注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

講解:

    (1) jpa:repositories:這一部分涉及到數據庫的接口,將在后面詳解;

    (2)entityManagerFactory:實體管理器工廠,讀取 persistence.xml 配置;

    (3)transactionManager:事務管理器,利用 entityManager 進行事務管理;

    (4)tx:annotation-driven:打開事務管理器的注解驅動,可以使用注解的方法操縱數據庫。

整體如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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"   # 此處要注意,默認的 tx 地址是 ../schema/catche, 此處需要更改,改為 黃色部分
       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-scan base-package="com.example.controller"/>  

    <!-- 靜態資源(js、image等)的訪問 -->
    <mvc:default-servlet-handler/>

    <!-- 開啟注解 -->
    <mvc:annotation-driven/>

    <!--ViewResolver 視圖解析器-->
    <!--用於支持Servlet、JSP視圖解析-->
    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 表示JPA Repository所在的包 -->
    <jpa:repositories base-package="com.example.repository"/>

    <!-- 鏈接到persistence.xml -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="defaultPersistenceUnit"/>
    </bean>

    <!-- 事務管理 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!-- 開啟事務管理注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
# 另,此文件 配置正確,無任何錯誤!!

下面,填充 persistence.xml將 persistence-unit 的 name改為 defaultPersistenceUnit。在下面的文件中,我添加了一些更為詳細的配置:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="defaultPersistenceUnit">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <!-- 使用MySQL方言 -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
            <!-- 數據庫連接的URL地址 -->
            <property name="hibernate.connection.url"
                      value="jdbc:mysql://localhost:3306/springdemo"/>
            <!-- 數據庫連接的驅動 -->
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <!-- 數據庫連接的用戶名 -->
            <property name="hibernate.connection.username" value="root"/>
            <!-- 數據庫連接的密碼 -->
            <property name="hibernate.connection.password" value="111111"/>
            <!-- 顯示SQL語句 -->
            <property name="hibernate.show_sql" value="true"/>

            <property name="hibernate.connection.useUnicode" value="true"/>
            <property name="hibernate.connection.characterEncoding" value="UTF-8"/>

            <!-- 在顯示SQL語句時格式化語句 -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="false"/>
            <!-- 自動輸出schema創建DDL語句 -->
            <property name="hbm2ddl.auto" value="update"/>

            <!-- 數據庫連接超時后自動重連 -->
            <property name="hibernate.connection.autoReconnect" value="true"/>
            <property name="connection.autoReconnectForPools" value="true"/>
            <property name="connection.is-connection-validation-required" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

 

現在,重新啟動 tomcat,如果沒有報錯,說明數據庫已經配置完成了,接下來就要講解數據庫的相關開發工作,另開一文:Java EE 學習(8):IDEA + maven + spring 搭建 web(4)- 用戶管理

 

更新(未嘗試):

      閱讀評論發現許多同學的persistence.xml出現了問題,因為出現問題的原因可能有很多,如果沒有完全的報錯以及代碼的話,我這邊很難解決問題,一個辦法就是在GitHub Issues上面提問並貼出代碼,我這邊盡量解答。另一個辦法就是下載最新的代碼運行看有沒有什么問題。

       最后一個辦法,嘗試另外一種配置方法,無需 persistence.xml,直接在 mvc-dispatcher-servlet.xml 中配置數據庫,如下所示:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="defaultPersistenceUnit"/>
        <property name="packagesToScan" value="com.example.model" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
                <prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/springdemo?useSSL=false</prop>
                <prop key="hibernate.connection.username">root</prop>
                <prop key="hibernate.connection.password">111111</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.connection.autoReconnect">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="connection.autoReconnectForPools">true</prop>
                <prop key="connection.is-connection-validation-required">true</prop>

                <prop key="hibernate.c3p0.validate">true</prop>
                <prop key="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</prop>
                <prop key="hibernate.c3p0.min_size">5</prop>
                <prop key="hibernate.c3p0.max_size">600</prop>
                <prop key="hibernate.c3p0.timeout">1800</prop>
                <prop key="hibernate.c3p0.max_statements">50</prop>
                <prop key="hibernate.c3p0.preferredTestQuery">SELECT 1;</prop>
                <prop key="hibernate.c3p0.testConnectionOnCheckout">true</prop>
                <prop key="hibernate.c3p0.idle_test_period">3000</prop>
            </props>
        </property>
    </bean>

 刪除persistence.xml,直接修改entityManagerFactory bean為如上圖所示。這個方法可以擺脫persistence.xml的困擾,但是有一個小小的問題,如果之前沒有添加Java EE Persistence這個框架的,文中的Persistence工具欄將不會顯示。一個解決辦法就是,先修改mvc-dispatcher-servlet,然后再添加Java EE Persistence框架,等能夠看到Persistence工具欄后,刪除persistence.xml,余下的步驟可以繼續操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM