JavaRush /จาวาบล็อก /Random-TH /ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate ...
Макс
ระดับ

ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 3)

เผยแพร่ในกลุ่ม
สวัสดีตอนบ่าย. ในบทความนี้ ฉันอยากจะแบ่งปันประสบการณ์ครั้งแรกของฉันกับสิ่งต่าง ๆ เช่น Maven, Spring, Hibernate, MySQL และ Tomcat ในกระบวนการสร้างแอปพลิเคชัน CRUD แบบง่าย นี่เป็นส่วนที่สามของ 4 บทความนี้มีไว้สำหรับผู้ที่ผ่านด่าน 30-40 ไปแล้วที่นี่ แต่ยังไม่ได้เสี่ยงเกินกว่า Java บริสุทธิ์และเพิ่งเริ่มต้น (หรือกำลังจะเริ่มต้น) เพื่อเข้าสู่โลกที่เปิดกว้างด้วย เทคโนโลยี กรอบงาน และคำอื่นๆ ที่ไม่คุ้นเคยทั้งหมดนี้ ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 3) - 1นี่เป็นส่วนที่สามของบทความ "ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก" สามารถดูภาคก่อนหน้าได้ตามลิงค์:

เนื้อหา:

การสร้างและการเชื่อมต่อฐานข้อมูล

ถึงเวลาเริ่มทำงานกับฐานข้อมูลแล้ว ก่อนที่จะเชื่อมต่อHibernateและคิดว่าควรจะทำงานอย่างไร ก่อนอื่นเรามาดูฐานข้อมูลกันก่อน เช่น มาสร้างมัน เชื่อมต่อ สร้างมัน และกรอกป้ายกัน เราจะใช้ DBMS (ระบบจัดการฐานข้อมูล) MySQL (แน่นอนว่าคุณต้องดาวน์โหลดและติดตั้งก่อน) SQL (Structured Query Language) เป็นภาษาโปรแกรมเชิงประกาศที่ใช้ในการสร้าง แก้ไข และจัดการข้อมูลในฐานข้อมูลเชิงสัมพันธ์ ในฐานข้อมูลดังกล่าว ข้อมูลจะถูกจัดเก็บในรูปแบบของตาราง แอปพลิเคชันสื่อสารกับฐานข้อมูลอย่างไร (ส่งคำสั่ง SQL ไปยังฐานข้อมูลและส่งกลับผลลัพธ์) สำหรับสิ่งนี้ Java มีสิ่งเช่นJDBC (การเชื่อมต่อ Java DataBase)ซึ่งพูดง่ายๆคือชุดของอินเทอร์เฟซและคลาสสำหรับการทำงานกับฐานข้อมูล หากต้องการโต้ตอบกับฐานข้อมูล คุณต้องสร้างการเชื่อมต่อ สำหรับสิ่งนี้ แพ็คเกจjava.sqlมีคลาสConnection. มีหลายวิธีในการสร้างการเชื่อมต่อ เช่น คุณสามารถใช้ เมธอด getConnectionคลาสDriverManagerได้ อย่างไรก็ตาม การโต้ตอบกับฐานข้อมูลไม่ได้ดำเนินการโดยตรง เนื่องจากมีฐานข้อมูลจำนวนมากและมีความแตกต่างกัน ดังนั้นสำหรับแต่ละอันจึงมีไดรเวอร์ JDBC ของตัวเอง เมื่อใช้ไดรเวอร์นี้การเชื่อมต่อกับฐานข้อมูลจะถูกสร้างขึ้น ดังนั้นก่อนอื่น เพื่อไม่ให้เสียสมาธิในภายหลัง มาติดตั้ง ไดรเวอร์ MySQL กันดี กว่า มาเพิ่มpom.xmlการพึ่งพาต่อไปนี้:
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>
ตอนนี้เรามาสร้างฐานข้อมูลกันดีกว่า ดู -> เครื่องมือ Windows -> ฐานข้อมูล - แผงฐานข้อมูลจะเปิดขึ้น ใหม่ (เขียว +) -> แหล่งข้อมูล -> MySQL - หน้าต่างจะเปิดขึ้นซึ่งคุณต้องระบุชื่อผู้ใช้และรหัสผ่านเราตั้งค่าไว้เมื่อติดตั้ง MySQL (เช่นตัวอย่างฉันใช้รูทและรูท) พอร์ต (ค่าเริ่มต้นสำหรับ MySQL 3306) ชื่อ ฯลฯ ปล่อยมันไว้เหมือนเดิม คุณสามารถทดสอบการเชื่อมต่อได้โดยใช้ปุ่ม " ทดสอบการเชื่อมต่อ " ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 3) - 2คลิกตกลงและตอนนี้เราเชื่อมต่อกับเซิร์ฟเวอร์ MySQL แล้ว ต่อไปเรามาสร้างฐานข้อมูลกัน เมื่อต้องการทำเช่นนี้ คุณสามารถเขียนสคริปต์ในคอนโซลที่เปิดขึ้น:
CREATE DATABASE test
คลิกExecuteและฐานข้อมูลพร้อม ตอนนี้คุณสามารถเชื่อมต่อได้แล้ว โดยกลับไปที่ Data Source Properties และป้อนชื่อฐานข้อมูล (ทดสอบ) ในช่อง Database จากนั้นป้อนชื่อผู้ใช้และรหัสผ่านอีกครั้ง แล้วคลิก OK ตอนนี้เราต้องจัดโต๊ะ คุณสามารถใช้เครื่องมือกราฟิกได้ แต่เป็นครั้งแรกที่คุณควรเขียนสคริปต์ด้วยมือเพื่อดูว่าหน้าตาเป็นอย่างไร:
USE test;

CREATE TABLE films
(
  id int(10) PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(100) NOT NULL,
  year int(4),
  genre VARCHAR(20),
  watched BIT DEFAULT false  NOT NULL
)
COLLATE='utf8_general_ci';
CREATE UNIQUE INDEX films_title_uindex ON films (title);

INSERT INTO `films` (`title`,`year`,`genre`, watched)
VALUES
  ("Inception", 2010, "sci-fi", 1),
  ("The Lord of the Rings: The Fellowship of the Ring", 2001, "fantasy", 1),
  ("Tag", 2018, "comedy", 0),
  ("Gunfight at the O.K. Corral", 1957, "western", 0),
  ("Die Hard", 1988, "action", 1);
ตารางถูกสร้างขึ้นด้วยชื่อที่filmsมีคอลัมน์idฯลฯ titleสำหรับแต่ละคอลัมน์ จะมีการระบุประเภท (ขนาดเอาต์พุตสูงสุดในวงเล็บ)
  • PRIMARY KEY- นี่คือคีย์หลัก ใช้เพื่อระบุระเบียนในตารางโดยไม่ซ้ำกัน (ซึ่งแสดงถึงความเป็นเอกลักษณ์)
  • AUTO_INCREMENT— ค่าจะถูกสร้างขึ้นโดยอัตโนมัติ (แน่นอนว่าจะไม่เป็นศูนย์ ดังนั้นคุณไม่จำเป็นต้องระบุสิ่งนี้)
  • NOT NULL- ที่นี่ทุกอย่างชัดเจนก็ไม่สามารถว่างเปล่าได้
  • DEFAULT— ตั้งค่าเริ่มต้น
  • COLLATE- การเข้ารหัส
  • CREATE UNIQUE INDEX- ทำให้สนามมีเอกลักษณ์เฉพาะตัว
  • INSERT INTO— เพิ่มบันทึกลงในตาราง
ผลลัพธ์ที่ได้คือสัญญาณดังนี้: บางทีอาจคุ้มค่าที่จะลองเชื่อมต่อแยกจากเว็บแอปพลิเคชันของเราในตอนนี้ จะเกิดอะไรขึ้นหากเกิดปัญหาขึ้นเราจะแก้ไขปัญหานี้ทันที มิฉะนั้นเราจะเชื่อมต่อในภายหลังไฮเบอร์เนตทำอะไรบางอย่างกำหนดค่าคนจรจัดและถ้าเราทำผิดพลาดที่ไหนสักแห่งอย่างน้อยเราก็จะได้รู้ว่าปัญหาไม่ได้อยู่ที่นี่ เพื่อตรวจสอบการเชื่อมต่อ เรามาสร้างวิธีการmainชั่วคราวกันดี กว่า โดยหลักการแล้ว คุณสามารถวางไว้ที่ใดก็ได้ แม้แต่ในคลาสคอนโทรลเลอร์ แม้แต่ในโมเดลหรือการกำหนดค่า ไม่สำคัญ คุณเพียงแค่ต้องใช้มันเพื่อให้แน่ใจว่าทุกอย่างเรียบร้อยดีกับการเชื่อมต่อ และคุณสามารถลบมันได้ แต่เพื่อให้ระมัดระวังมากขึ้น เรามาสร้างคลาสแยกต่างหากกันดีกว่าMain:
package testgroup.filmography;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/test";
        String username = "root";
        String password = "root";
        System.out.println("Connecting...");

        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            System.out.println("Connection successful!");
        } catch (SQLException e) {
            System.out.println("Connection failed!");
            e.printStackTrace();
        }
    }
}
ทุกอย่างเป็นเรื่องง่ายที่นี่ เราตั้งค่าพารามิเตอร์การเชื่อมต่อให้กับฐานข้อมูลของเราและพยายามสร้างการเชื่อมต่อ เปิดตัวอันนี้mainแล้วลองดูครับ ฉันได้รับข้อยกเว้น ปัญหาเกี่ยวกับเขตเวลา และคำเตือนอื่นๆ เกี่ยวกับ SSL หลังจากท่องอินเทอร์เน็ตคุณจะพบว่านี่เป็นปัญหาที่พบบ่อยและเมื่อใช้ไดรเวอร์เวอร์ชันต่าง ๆ (mysql-connector-java) ก็สามารถสาบานได้แตกต่างออกไป ตัวอย่างเช่น ฉันค้นพบการทดลองว่าเมื่อใช้เวอร์ชัน 5.1.47 ไม่มีข้อยกเว้นเนื่องจากเขตเวลา การเชื่อมต่อจะถูกสร้างขึ้นตามปกติ แต่คำเตือน SSL ยังคงปรากฏขึ้น สำหรับเวอร์ชันอื่นๆ ดูเหมือนว่ามีข้อยกเว้นเกี่ยวกับ SSL และไม่ใช่แค่คำเตือน โอเค นั่นไม่ใช่ประเด็น คุณสามารถลองจัดการกับปัญหานี้แยกกัน แต่เราจะไม่เข้าไปแก้ไขปัญหาในตอนนี้ วิธีแก้ปัญหานี้ค่อนข้างง่าย คุณต้องระบุพารามิเตอร์เพิ่มเติมในurlกล่าวคือserverTimezoneหากปัญหาอยู่ที่เขตเวลา และuseSSLหากปัญหาอยู่ที่ SSL:
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Europe/Minsk&useSSL=false";
ตอนนี้เราได้ตั้งค่าเขตเวลาและปิดการใช้งาน SSL แล้ว เราเปิดตัวอีกครั้งmainและ voila - การเชื่อมต่อสำเร็จ! เยี่ยมเลย เรารู้วิธีสร้างการเชื่อมต่อแล้ว โดยพื้นฐานแล้ว ชั้นเรียนMainทำงานเสร็จแล้ว คุณสามารถลบออกได้

ออมและ JPA

ในทางที่ดี เพื่อความเข้าใจที่ดีขึ้น เป็นการดีกว่าที่จะเริ่มทำความคุ้นเคยกับฐานข้อมูลตามลำดับตั้งแต่เริ่มต้น โดยไม่ต้องจำศีลหรือสิ่งอื่นๆ ดังนั้นจึงเป็นความคิดที่ดีที่จะค้นหาคำแนะนำและลองทำงานกับคลาส JDBC ก่อน เขียนคำสั่ง SQL ด้วยตนเอง และอื่นๆ มาดู โมเดล ORMกันดีกว่า สิ่งนี้หมายความว่า? แน่นอนว่าขอแนะนำให้อ่านเกี่ยวกับเรื่องนี้แยกกันอีกครั้ง แต่ฉันจะพยายามอธิบายสั้น ๆ ORM (Object-Relational Mapping หรือ object-relational mapping) เป็นเทคโนโลยีสำหรับการแมปออบเจ็กต์ลงในโครงสร้างฐานข้อมูลเชิงสัมพันธ์ เช่น เพื่อแสดงวัตถุ Java ของเราเป็นแถวของตาราง ด้วย ORM คุณจึงไม่ต้องกังวลกับการเขียนสคริปต์ SQL และมุ่งเน้นไปที่การทำงานกับอ็อบเจ็กต์ วิธีการใช้งาน Java มีข้อดีอีกประการหนึ่งคือ JPA (Java Persistence API) ซึ่งใช้แนวคิด ORM JPA เป็นข้อกำหนด โดยอธิบายข้อกำหนดสำหรับออบเจ็กต์ กำหนดอินเทอร์เฟซและคำอธิบายประกอบต่างๆ สำหรับการทำงานกับฐานข้อมูล JPA โดยพื้นฐานแล้วคือคำอธิบายซึ่งเป็นมาตรฐาน ดังนั้นจึงมีการใช้งานเฉพาะหลายอย่าง หนึ่งในนั้น (และหนึ่งในความนิยมมากที่สุด) คือ Hibernate ซึ่งเป็นแก่นแท้ของเฟรมเวิร์กนี้ Hibernate คือการนำข้อกำหนด JPA ไปใช้ที่ออกแบบมาเพื่อแก้ไขปัญหาการทำแผนที่เชิงวัตถุ (ORM) เราจำเป็นต้องเชื่อมโยงสิ่งทั้งหมดนี้กับโครงการของเรา นอกจากนี้เพื่อให้ Spring ของเราไม่ยืนข้างสนามและมีส่วนร่วมในการเคลื่อนไหวทั้งหมดนี้กับฐานข้อมูลเราจำเป็นต้องเชื่อมต่อโมดูลเพิ่มเติมอีกสองสามโมดูลเพราะ ทุกสิ่งที่เราได้รับจาก การพึ่งพา spring-webmvcนั้นไม่เพียงพอสำหรับสิ่งนี้อีกต่อไป นอกจากนี้เรายังต้องการspring-jdbcเพื่อทำงานกับฐานข้อมูลspring-txเพื่อรองรับธุรกรรม และspring-ormเพื่อทำงานกับ Hibernate มาเพิ่มการพึ่งพาไปที่pom.xml:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>5.1.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.3.7.Final</version>
</dependency>
การพึ่งพาทั้งสองนี้ก็เพียงพอแล้ว javax.persistence-apiจะมาถึงพร้อมกับhibernate-coreและspring-jdbcและspring-txพร้อมกับspring- orm

เอนทิตี

ดังนั้นเราจึงต้องการให้วัตถุคลาสFilmสามารถเก็บไว้ในฐานข้อมูลได้ เมื่อต้องการทำเช่นนี้ ชั้นเรียนต้องตรงตามเงื่อนไขหลายประการ ใน JPA มีสิ่งที่เป็น เอนทิตีสำหรับสิ่งนี้ คลาสเอนทิตีคือ คลาส POJO ธรรมดา โดยมีฟิลด์ส่วนตัว และ getters และ setters สำหรับพวกมัน ต้องมีตัวสร้างที่ไม่ใช่ส่วนตัวโดยไม่มีพารามิเตอร์ (หรือตัวสร้างเริ่มต้น) และต้องมีคีย์หลัก เช่น สิ่งที่จะระบุแต่ละบันทึกของคลาสนี้ในฐานข้อมูลโดยไม่ซ้ำกัน คุณยังสามารถอ่านเกี่ยวกับข้อกำหนดทั้งหมดสำหรับชั้นเรียนดังกล่าวแยกกันได้ มาทำให้ชั้นเรียนของเราFilmเป็นเอนทิตีโดยใช้คำอธิบายประกอบ JPA:
package testgroup.filmography.model;

import javax.persistence.*;

@Entity
@Table(name = "films")
public class Film {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "title")
    private String title;

    @Column(name = "year")
    private int year;

    @Column(name = "genre")
    private String genre;

    @Column(name = "watched")
    private boolean watched;

    // + getters and setters
}
  • @Entity- ระบุว่าคลาสนี้เป็นเอนทิตี
  • @Table- ชี้ไปที่ตารางเฉพาะเพื่อแสดงเอนทิตีนี้
  • @Id— ระบุว่าฟิลด์นี้เป็นคีย์หลัก เช่น คุณสมบัตินี้จะใช้เพื่อระบุแต่ละรายการที่ไม่ซ้ำ
  • @Column— เชื่อมต่อเขตข้อมูลกับคอลัมน์ตาราง ถ้าชื่อคอลัมน์เขตข้อมูลและตารางเหมือนกัน คุณสามารถละเว้นได้
  • @GeneratedValue— คุณสมบัติจะถูกสร้างขึ้นโดยอัตโนมัติ คุณสามารถระบุวิธีการได้ในวงเล็บ ตอนนี้เราจะไม่เข้าใจว่ากลยุทธ์ที่แตกต่างกันทำงานอย่างไร ก็เพียงพอที่จะรู้ว่าในกรณีนี้แต่ละค่าใหม่จะเพิ่มขึ้น 1 จากค่าก่อนหน้า
สำหรับแต่ละคุณสมบัติ คุณสามารถระบุสิ่งอื่นๆ เพิ่มเติมได้ เช่น สิ่งที่ควรไม่เป็นศูนย์หรือไม่ซ้ำกัน ระบุค่าเริ่มต้น ขนาดสูงสุด เป็นต้น สิ่งนี้จะมีประโยชน์หากคุณต้องการสร้างตารางตามคลาสนี้ Hibernate มีตัวเลือกนี้ แต่เราได้สร้างตารางขึ้นมาเองและกำหนดค่าคุณสมบัติทั้งหมดแล้ว ดังนั้นเราจึงสามารถทำได้โดยไม่ต้องใช้มัน บันทึกเล็กๆ น้อยๆเอกสาร Hibernate แนะนำให้ใช้คำอธิบายประกอบที่ไม่ได้อยู่ในฟิลด์ แต่ใน getters อย่างไรก็ตาม ความแตกต่างระหว่างแนวทางเหล่านี้ค่อนข้างละเอียดอ่อน และในแอปพลิเคชันที่เรียบง่ายของเรา สิ่งนี้จะไม่ส่งผลกระทบใดๆ นอกจากนี้ คนส่วนใหญ่ยังใส่คำอธิบายประกอบไว้เหนือฟิลด์อีกด้วย เลยปล่อยไว้แบบนี้ก็ดูเรียบร้อยขึ้นครับ

คุณสมบัติไฮเบอร์เนต

เรามาเริ่มตั้งค่าไฮเบอร์เนตของเรากันดีกว่า ก่อนอื่น เรามาใส่ข้อมูลบางอย่าง เช่น ชื่อผู้ใช้และรหัสผ่าน url และอย่างอื่นลงในไฟล์แยกต่างหาก แน่นอนคุณสามารถระบุให้เป็นบรรทัดปกติได้โดยตรงในชั้นเรียน เช่นเดียวกับที่เราทำเมื่อเราตรวจสอบการเชื่อมต่อ ( String username = "root";แล้วส่งต่อไปยังวิธีการสร้างการเชื่อมต่อ) แต่ก็ยังถูกต้องกว่าในการจัดเก็บข้อมูลคงที่ดังกล่าวในpropertyไฟล์ บางไฟล์ และหากคุณต้องการเปลี่ยนฐานข้อมูลคุณไม่จำเป็นต้องผ่านคลาสทั้งหมดและดูว่ามันใช้งานที่ไหน แค่เปลี่ยนค่าในไฟล์นี้ครั้งเดียวก็เพียงพอแล้ว มาสร้าง ไฟล์db.propertiesใน ไดเร็กทอรี ทรัพยากร :
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?serverTimezone=Europe/Minsk&useSSL=false
jdbc.username=root
jdbc.password=root

hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
hibernate.show_sql=true
จากด้านบนทุกอย่างชัดเจน พารามิเตอร์สำหรับการเชื่อมต่อกับฐานข้อมูล เช่น ชื่อคลาสไดรเวอร์, URL, ชื่อผู้ใช้และรหัสผ่าน hibernate.dialect- คุณสมบัตินี้จำเป็นเพื่อระบุให้ Hibernate ทราบว่าใช้ภาษา SQL เวอร์ชันใด ความจริงก็คือในทุก ๆ DBMS เพื่อที่จะขยายขีดความสามารถ เพิ่มฟังก์ชันการทำงานบางอย่าง หรือเพิ่มประสิทธิภาพบางอย่าง พวกเขามักจะปรับปรุงภาษาให้ทันสมัยเล็กน้อย เป็นผลให้ปรากฎว่าแต่ละ DBMS มีภาษา SQL ของตัวเอง ก็เหมือนกับภาษาอังกฤษที่ดูเหมือนภาษาจะเหมือนกัน แต่ในออสเตรเลีย สหรัฐอเมริกา หรืออังกฤษ จะมีความแตกต่างกันเล็กน้อย และบางคำก็อาจมีความหมายต่างกัน และเพื่อหลีกเลี่ยงปัญหาในการทำความเข้าใจ คุณต้องบอก Hibernate โดยตรงว่าต้องจัดการกับอะไร hibernate.show_sql— ด้วยคุณสมบัตินี้ การสืบค้นไปยังฐานข้อมูลจะแสดงในคอนโซล สิ่งนี้ไม่จำเป็น แต่อย่างน้อยด้วยสิ่งนี้คุณสามารถดูสิ่งที่เกิดขึ้นได้ไม่เช่นนั้นไฮเบอร์เนตอาจดูเหมือนกำลังทำเวทมนตร์บางอย่างอยู่ แน่นอนว่าการแสดงจะไม่ชัดเจนนัก ควรใช้ตัวบันทึกบางประเภทสำหรับสิ่งนี้ แต่นั่นเป็นอย่างอื่นสำหรับตอนนี้ก็คงจะเป็นเช่นนั้น

การกำหนดค่าไฮเบอร์เนต

มาดูการตั้งค่ากันต่อ configมาสร้าง คลาสในแพ็คเกจกัน เถอะ HibernateConfig:
package testgroup.filmography.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@ComponentScan(basePackages = " testgroup.filmography")
@EnableTransactionManagement
@PropertySource(value = "classpath:db.properties")
public class HibernateConfig {
    private Environment environment;

    @Autowired
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        return properties;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan("testgroup.filmography.model");
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }
}
มีสิ่งใหม่ๆ ค่อนข้างมากที่นี่ ดังนั้นจึงเป็นการดีที่สุดที่จะค้นหาข้อมูลเพิ่มเติมเกี่ยวกับแต่ละรายการจากแหล่งต่างๆ เรามาดูกันสั้น ๆ ที่นี่
  • เรา รู้ @Configurationแล้ว@ComponentScanว่าเราเรียนจบเมื่อWebConfigไหร่
  • @EnableTransactionManagement— ช่วยให้คุณใช้มันTransactionManagerเพื่อจัดการธุรกรรม Hibernate ทำงานร่วมกับฐานข้อมูลโดยใช้ธุรกรรม ซึ่งจำเป็นสำหรับชุดการดำเนินการบางชุดที่จะดำเนินการโดยรวมทั้งหมด เช่น หากวิธีการมีปัญหากับการดำเนินการใด ๆ การดำเนินการอื่น ๆ ทั้งหมดจะไม่ถูกดำเนินการเพื่อไม่ให้เกิดขึ้นเหมือนในตัวอย่างคลาสสิกกับการโอนเงินเมื่อการดำเนินการถอนเงินจากบัญชีเดียวเสร็จสิ้น แต่ การดำเนินการเขียนถึงผู้อื่นไม่ได้ผลส่งผลให้เงินหายไป
  • @PropertySource— เชื่อมต่อไฟล์คุณสมบัติที่เราเพิ่งสร้างขึ้น
  • Environment- เพื่อรับคุณสมบัติจากpropertyไฟล์
  • hibernateProperties- จำเป็นต้องใช้วิธีนี้เพื่อแสดงคุณสมบัติ Hibernate เป็นวัตถุ Properties
  • DataSource— ใช้เพื่อสร้างการเชื่อมต่อกับฐานข้อมูล นี่เป็นอีกทางเลือกหนึ่งสำหรับDriverManagerซึ่งเราใช้ก่อนหน้านี้เมื่อเราสร้างไฟล์main. เอกสารบอกว่าDataSourceควรใช้ดีกว่า แน่นอนว่านั่นคือสิ่งที่เราจะทำ อย่าลืมอ่านบนอินเทอร์เน็ตว่าความแตกต่างและข้อดีคืออะไร ข้อดีประการหนึ่งคือความสามารถในการสร้าง Database Connection Pool (DBCP)
  • sessionFactory— เพื่อสร้างเซสชันด้วยความช่วยเหลือในการดำเนินการกับออบเจ็กต์เอนทิตี ที่นี่เราตั้งค่าแหล่งข้อมูล คุณสมบัติ Hibernate และแพ็คเกจที่เราจำเป็นต้องค้นหาคลาสเอนทิตี
  • transactionManager— เพื่อกำหนดค่าตัวจัดการธุรกรรม
บันทึกเล็กๆ น้อยๆ เกี่ยวกับDataSource. เอกสารระบุว่าDriverManagerDataSourceไม่แนะนำให้ใช้การดำเนินการมาตรฐาน กล่าวคือ เนื่องจาก เป็นเพียงการทดแทนการรวมการเชื่อมต่อแบบปกติเท่านั้น และโดยทั่วไปเหมาะสำหรับการทดสอบและอื่นๆ เท่านั้น สำหรับแอปพลิเคชันทั่วไป ควรใช้ไลบรารี DBCP บางประเภทมากกว่า แน่นอนว่าสำหรับแอปพลิเคชันของเรา สิ่งที่เรามีอยู่ก็เพียงพอแล้ว แต่เพื่อให้ภาพสมบูรณ์ บางทีเราอาจยังคงใช้การดำเนินการอื่นตามที่แนะนำ มาเพิ่มpom.xmlการพึ่งพาต่อไปนี้:
<dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-dbcp</artifactId>
            <version>9.0.10</version>
</dependency>
และในdataSourceclass method HibernateConfigเราจะแทนที่มันDriverManagerDataSourceด้วยBasicDataSourceone จาก package org.apache.tomcat.dbcp.dbcp2:
BasicDataSource dataSource = new BasicDataSource();
ดูเหมือนว่าทุกอย่างจะพร้อมแล้ว การกำหนดค่าพร้อมแล้ว สิ่งที่เหลืออยู่คือการเพิ่มลงในAppInitializer ของเรา :
protected Class<?>[] getRootConfigClasses() {
        return new Class[]{HibernateConfig.class};
    }

ชั้นการเข้าถึงข้อมูล

ถึงเวลาเริ่มต้นใช้งาน DAO ของเราในที่สุด เราไปชั้นเรียนFilmDAOImplและก่อนอื่นลบรายการทดลองออกจากที่นั่น เราไม่ต้องการมันอีกต่อไป มาเพิ่มโรงงานเซสชั่นและดำเนินการผ่านมันกัน
private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
ขั้นแรกเราจะสร้างวิธีการแสดงหน้าพร้อมรายชื่อภาพยนตร์โดยในนั้นเราจะได้รับเซสชันและทำการร้องขอไปยังฐานข้อมูล (ดึงบันทึกทั้งหมดออกและสร้างรายการ):
public List<Film> allFilms() {
        Session session = sessionFactory.getCurrentSession();
        return session.createQuery("from Film").list();
    }
มี 2 ​​จุดตรงนี้. ประการแรก มีการแสดงคำเตือน นี่เป็นเพราะความจริงที่ว่าเราต้องการรับพารามิเตอร์List<Film>แต่เมธอดส่งคืนเพียงListเพราะ ณ เวลาคอมไพล์นั้นไม่รู้ว่าคำขอจะส่งกลับประเภทใด แนวคิดนี้เตือนเราว่าเรากำลังทำการแปลงที่ไม่ปลอดภัย ซึ่งอาจส่งผลให้เกิดปัญหาได้ มีหลายวิธีที่ถูกต้องในการทำเช่นนี้เพื่อไม่ให้เกิดคำถามดังกล่าว คุณสามารถค้นหาข้อมูลบนอินเทอร์เน็ตได้ แต่อย่าไปสนใจเรื่องนี้ตอนนี้เลย ความจริงก็คือเรารู้แน่ชัดว่าจะต้องส่งคืนประเภทใด ดังนั้นจึงไม่มีปัญหาเกิดขึ้นที่นี่ คุณเพียงแค่เพิกเฉยต่อคำเตือนก็ได้ แต่เพื่อไม่ให้ดวงตาของคุณแสบตา คุณสามารถใส่คำอธิบายประกอบไว้เหนือวิธีการ@SupressWarning("unchecked")ได้ การทำเช่นนี้เป็นการบอกคอมไพเลอร์ว่า ขอบคุณเพื่อน สำหรับความกังวลของคุณ แต่ฉันรู้ว่าฉันกำลังทำอะไรอยู่และควบคุมทุกอย่างได้ ดังนั้นคุณจึงผ่อนคลายและไม่ต้องกังวลกับวิธีนี้ ประการที่สอง แนวคิดนี้ขีดเส้นใต้ด้วยสีแดง " from Film" เป็นเพียงแบบสอบถาม HQL (Hibernate Query Language) และแนวคิดนี้ไม่เข้าใจว่าทุกอย่างถูกต้องหรือมีข้อผิดพลาด คุณสามารถไปที่การตั้งค่าแนวคิดและปรับทุกอย่างด้วยตนเอง (หากสนใจดูบนอินเทอร์เน็ต) หรือคุณสามารถเพิ่มการสนับสนุนสำหรับกรอบงาน Hibernate โดยคลิกขวาที่โครงการ เลือกAdd Framework Supportทำเครื่องหมายที่ช่องHibernateแล้วคลิก OK หลังจากนี้ เป็นไปได้มากในคลาสเอนทิตี ( Film) หลายสิ่งหลายอย่างจะถูกขีดเส้นใต้ด้วยสีแดง เช่น โดยที่คำอธิบายประกอบ@Table(name = "films")จะออกคำเตือนไม่สามารถแก้ไขตาราง 'ภาพยนตร์' ขอย้ำอีกครั้งว่าไม่มีอะไรผิดปกติ นี่ไม่ใช่ข้อผิดพลาดในการออกแบบ ทุกอย่างจะคอมไพล์และใช้งานได้ แนวคิดนี้ได้รับการเน้นย้ำเนื่องจากไม่รู้อะไรเลยเกี่ยวกับฐานของเรา เพื่อแก้ไขปัญหานี้ เรามารวมแนวคิดเข้ากับฐานข้อมูลกันดีกว่า View -> Tool Windows -> Persistense (แท็บจะเปิดขึ้น) -> ปุ่มเมาส์ขวา เลือก Assign Data Sources -> ใน Data Source ระบุการเชื่อมต่อกับฐานข้อมูลแล้วคลิก OK ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 3) - 3เมื่อทั้งหมดนี้ได้รับการแก้ไขแล้ว ยังมีบางสิ่งเหลืออยู่ ไปที่ระดับที่สูงขึ้นเพื่อการบริการ ในชั้นเรียนFilmServiceImplเราทำเครื่องหมายallFilmsวิธี spring ด้วยคำอธิบายประกอบ@Transactionalซึ่งจะระบุว่าควรดำเนินการวิธีการดังกล่าวในธุรกรรม (หากไม่มีสิ่งนี้ Hibernate จะปฏิเสธที่จะทำงาน):
@Transactional
public List<Film> allFilms() {
    return filmDAO.allFilms();
}
ทุกอย่างพร้อมแล้วที่นี่ คุณไม่จำเป็นต้องแตะสิ่งใดในคอนโทรลเลอร์ ดูเหมือนว่าช่วงเวลาแห่งความจริงมาถึงแล้ว คลิกเรียกใช้แล้วดูว่าจะเกิดอะไรขึ้น ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 3) - 4และนี่คือสัญญาณของเรา และครั้งนี้ไม่ได้มาจากรายการที่เราทำเองในชั้นเรียน แต่มาจากฐานข้อมูล เยี่ยมมาก ทุกอย่างดูเหมือนจะทำงานได้ ตอนนี้เราทำการดำเนินการ CRUD อื่นๆ ทั้งหมดในลักษณะเดียวกันโดยใช้วิธีเซสชัน คลาสผลลัพธ์จะมีลักษณะดังนี้:
package testgroup.filmography.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import testgroup.filmography.model.Film;

import java.util.List;

@Repository
public class FilmDAOImpl implements FilmDAO {
    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Film> allFilms() {
        Session session = sessionFactory.getCurrentSession();
        return session.createQuery("from Film").list();
    }

    @Override
    public void add(Film film) {
        Session session = sessionFactory.getCurrentSession();
        session.persist(film);
    }

    @Override
    public void delete(Film film) {
        Session session = sessionFactory.getCurrentSession();
        session.delete(film);
    }

    @Override
    public void edit(Film film) {
        Session session = sessionFactory.getCurrentSession();
        session.update(film);
    }

    @Override
    public Film getById(int id) {
        Session session = sessionFactory.getCurrentSession();
        return session.get(Film.class, id);
    }
}
ตอนนี้สิ่งที่เหลืออยู่คืออย่าลืมไปที่บริการและเพิ่มคำอธิบายประกอบให้กับวิธีการ@Transactionalต่างๆ เท่านี้ก็พร้อมแล้ว ตอนนี้คุณสามารถเรียกใช้และตรวจสอบได้ คลิกลิงก์และปุ่ม พยายามเพิ่ม/ลบ/แก้ไขรายการ หากทุกอย่างถูกต้องก็ควรจะทำงานได้ ตอนนี้เป็นแอปพลิเคชัน CRUD เต็มรูปแบบที่ใช้ Hibernate, Spring, MySQL ดำเนินการต่อ... ขอแนะนำ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 1) ขอแนะนำ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 2) ขอแนะนำ Maven, Spring, MySQL, Hibernate และ แอปพลิเคชัน CRUD แรก (ตอนที่ 3) ข้อมูลเบื้องต้นเกี่ยวกับ Maven, Spring, MySQL, Hibernate และแอปพลิเคชัน CRUD แรก (ตอนที่ 4)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION