JavaRush /Java Blog /Random-KO /첫 번째 Hibernate 애플리케이션

첫 번째 Hibernate 애플리케이션

Random-KO 그룹에 게시되었습니다
이 기사에서는 가장 널리 사용되는 Java용 엔터프라이즈 프레임워크 중 하나에 대해 알아보고 Hibernate를 사용하여 첫 번째 애플리케이션을 작성합니다. 최대 절전 모드에 대해 들어본 적이 없나요? 들어본 적은 있지만 사용해 본 적이 없으신가요? 아니면 시작하려고 했지만 성공하지 못하셨나요? 세 가지 경우 모두 컷에 오신 것을 환영합니다 :) 첫 번째 Hibernate 애플리케이션 - 1안녕하세요 여러분! 이 기사에서는 Hibernate 프레임워크의 주요 기능에 대해 이야기하고 첫 번째 미니 애플리케이션을 작성하는 데 도움을 줄 것입니다. 이를 위해서는 다음이 필요합니다.
  1. Intellij 아이디어 얼티밋 에디션; 공식 웹사이트
    에서 다운로드 하고 30일 평가판을 활성화하세요.
  2. PostgeSQL은 가장 널리 사용되는 최신 데이터베이스 관리 시스템(DBMS) 중 하나입니다.
  3. Maven(이미 IDEA에 내장되어 있음)
  4. 약간의 인내심.
이 기사는 주로 이 기술을 사용해 본 적이 없는 사람들을 대상으로 하므로 코드의 양을 최대한 줄였습니다. 시작하자!

최대 절전 모드란 무엇입니까?

이는 ORM 모델의 가장 널리 사용되는 구현 중 하나입니다. 객체-관계형 모델은 데이터베이스의 소프트웨어 객체와 레코드 간의 관계를 설명합니다. 물론 Hibernate의 기능은 매우 광범위하지만 우리는 가장 간단한 기능에 중점을 둘 것입니다. 우리의 목표: 다음을 수행할 수 있는 CRUD 애플리케이션(생성, 읽기, 업데이트, 삭제)을 만드는 것입니다.
  1. 사용자(User)를 생성하고, ID로 데이터베이스에서 검색하고, 데이터베이스에서 데이터를 업데이트하고, 데이터베이스에서 삭제합니다.
  2. 사용자에게 차량 개체(자동)를 할당합니다. 데이터베이스에서 자동차를 생성, 편집, 검색 및 삭제합니다.
  3. 또한 애플리케이션은 데이터베이스에서 "고아" 자동차를 자동으로 제거해야 합니다. 저것들. 사용자가 삭제되면 해당 사용자에게 속한 모든 차량도 데이터베이스에서 삭제되어야 합니다.
우리 프로젝트의 구조는 다음과 같습니다. 첫 번째 Hibernate 애플리케이션 - 2보시다시피 복잡한 것은 없습니다. 6개 클래스 + 구성이 포함된 1개 파일. 먼저 Intellij Idea에서 새로운 Maven 프로젝트를 생성해 보겠습니다. 파일 -> 새 프로젝트. 제안된 프로젝트 유형에서 Maven을 선택하고 계속 진행합니다. 첫 번째 Hibernate 애플리케이션 - 3Apache Maven은 POM 언어로 된 파일의 구조 설명을 기반으로 프로젝트 어셈블리를 자동화하는 프레임워크입니다. 프로젝트의 전체 구조는 IDEA 자체가 프로젝트 루트에 생성하는 pom.xml 파일에 설명됩니다. 프로젝트 설정에서 Maven 매개변수(groupId 및 ArtifactId)를 지정해야 합니다. 일반적으로 프로젝트에서 groupId는 조직 또는 부서의 이름이며 해당 조직 또는 프로젝트 사이트의 도메인 이름이 여기에 기록됩니다. 결과적으로, ArtifactId는 프로젝트의 이름입니다. groupdId의 경우 를 지정할 수 있습니다 com.вашНикнейм.javarush. 이는 어떤 방식으로든 애플리케이션 작동에 영향을 미치지 않습니다. ArtifactId의 경우 원하는 프로젝트 이름을 선택합니다. 버전을 변경하지 않고 그대로 둘 수도 있습니다. 첫 번째 Hibernate 애플리케이션 - 4마지막 화면에서는 이전에 입력한 데이터를 확인하세요. 첫 번째 Hibernate 애플리케이션 - 5이제 우리는 프로젝트를 만들었습니다. 남은 것은 코드를 작성하고 작동하게 만드는 것뿐입니다. :) 우선, 데이터베이스와 함께 작동하는 애플리케이션을 만들고 싶다면 데이터베이스 없이는 절대 할 수 없습니다! 여기에서 PostgreSQL을 다운로드하세요 (저는 버전 9를 사용합니다). PostgreSQL에는 기본 사용자 'postgres'가 있으므로 설치 중에 비밀번호를 생성해야 합니다. 나중에 필요하므로 비밀번호를 잊지 마세요! (일반적으로 애플리케이션에서 기본 데이터베이스를 사용하는 것은 나쁜 습관이지만, 치질의 양을 줄이기 위해 자체 데이터베이스를 생성하겠습니다.) 명령줄과 SQL 쿼리에 익숙하지 않다면 좋은 소식이 있습니다. Intellij IDEA는 데이터베이스 작업에 매우 적합한 사용자 인터페이스를 제공합니다. 다음과 같습니다: 첫 번째 Hibernate 애플리케이션 - 6(IDEA의 오른쪽 사이드바, 데이터베이스 탭에 위치) 연결을 생성하려면 "+"를 클릭하고 공급자(PostgeSQL)를 선택합니다. 사용자, 데이터베이스 이름(둘 다 postgres)으로 필드를 채우고 PostgreSQL을 설치할 때 설정한 비밀번호를 입력합니다. 필요한 경우 Postgres 드라이버를 다운로드하십시오. 이 작업은 동일한 페이지에서 수행할 수 있습니다. "연결 테스트"를 클릭하여 데이터베이스에 대한 연결이 설정되었는지 확인하세요. "성공"이라는 문구가 보이면 계속 진행합니다. 이제 필요한 테이블을 만들어 보겠습니다. 사용자와 자동차라는 두 가지가 있습니다. 사용자 테이블의 매개변수: Hibernate에서의 첫 번째 애플리케이션 - 7id가 기본 키라는 점에 유의하세요. SQL의 기본 키가 무엇인지 모른다면 Google에서 검색하는 것이 중요합니다. autos 테이블 설정: Hibernate에서의 첫 번째 애플리케이션 - 8자동차의 경우 외래 키 - 외래 키를 구성해야 합니다. 그것은 우리 테이블을 연결할 것입니다. 그에 대해 더 읽어 보시기 바랍니다. 매우 간단히 말하면 외부 테이블(이 경우에는 사용자)을 나타냅니다. 자동차가 id=1인 사용자에게 속해 있으면 autos 테이블의 user_id 필드에 1이 표시됩니다. 이것이 애플리케이션에서 사용자를 자동차와 연결하는 방법입니다. autos 테이블에서 user_id 필드는 외래 키 역할을 합니다. 이는 사용자 테이블의 id 필드를 참조합니다. 첫 번째 Hibernate 애플리케이션 - 9따라서 우리는 두 개의 테이블로 구성된 데이터베이스를 만들었습니다. Java 코드에서 이를 관리하는 방법을 이해하는 것이 남아 있습니다. 필요한 라이브러리(Maven 언어에서는 종속성이라고 함)를 포함해야 하는 pom.xml 파일부터 시작하겠습니다. 모든 라이브러리는 중앙 Maven 저장소에 저장됩니다. pom.xml에 지정한 것들은 프로젝트에서 사용할 수 있습니다. pom.xml은 다음과 같아야 합니다. 첫 번째 Hibernate 애플리케이션 - 10보시다시피 복잡한 것은 없습니다. PostgreSQL과 Hibernate를 사용하기 위해 2개의 종속성만 추가했습니다. 이제 Java 코드로 넘어가겠습니다. 프로젝트에 필요한 모든 패키지와 클래스를 만듭니다. 우선, 클래스 UserAuto.
package models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table (name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(name = "name")
    private String name;
    //you can not specify Column name if it matches the name of the column in the table
    private int age;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Auto> autos;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        autos = new ArrayList<>();
    }

    public void addAuto(Auto auto) {
        auto.setUser(this);
        autos.add(auto);
    }

    public void removeAuto(Auto auto) {
        autos.remove(auto);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<Auto> getAutos() {
        return autos;
    }

    public void setAutos(List<Auto> autos) {
        this.autos = autos;
    }

    @Override
    public String toString() {
        return "models.User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package models;

import javax.persistence.*;

@Entity
@Table(name = "autos")
public class Auto {

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

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

    //you can not specify Column name if it matches the name of the column in the table
    private String color;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    public Auto() {
    }

    public Auto(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public int getId() {
        return id;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return color + " " + model;
    }
}
보시다시피, 클래스에는 여전히 불분명한 주석이 많이 포함되어 있습니다. 그들을 다루기 시작합시다. 우리의 주요 주석은 @Entity입니다. Wikipedia에서 이에 대해 읽고 모든 것을 기억하십시오. 이것이 기본의 기초입니다. 이 주석을 사용하면 클래스의 Java 객체를 데이터베이스와 연결할 수 있습니다. 클래스가 엔터티가 되려면 다음 요구 사항을 충족해야 합니다.
  • 빈 생성자( public또는 protected)가 있어야 합니다.
  • 중첩, 인터페이스 또는 enum;
  • -fields/properties 일 수도 없고 final포함할 수도 없습니다 .final
  • @Id 필드가 하나 이상 포함되어야 합니다.
엔터티 클래스를 확인하세요. 이곳은 발에 총을 쏠 수 있는 매우 인기 있는 장소입니다. 무언가를 잊는 것은 매우 쉽습니다. 이 경우 기업은 다음을 수행할 수 있습니다.
  • 비어 있지 않은 생성자를 포함합니다.
  • 상속받는 것과 상속받는 것;
  • 다른 메서드를 포함하고 인터페이스를 구현합니다.
보시다시피 클래스는 User사용자 테이블과 매우 유사합니다. id, name, 필드가 있습니다 age. 그 위에 있는 주석에는 많은 설명이 필요하지 않습니다. @Id가 해당 필드가 이 클래스 개체의 식별자임을 나타내는 것은 이미 분명합니다. 클래스 위의 @Table 주석은 객체가 기록되는 테이블의 이름을 지정합니다. age 필드 위의 설명에 주의하세요. 클래스와 테이블의 필드 이름이 동일한 경우 @Column 주석을 추가할 필요가 없으며 그렇게 작동합니다. 괄호 안에 표시된 "strategy = GenerationType.IDENTITY"에 대해 여러 가지 ID 생성 전략이 있습니다. Google에서 검색할 수 있지만 애플리케이션 프레임워크 내에서는 귀찮게 할 필요가 없습니다. 가장 중요한 점은 객체의 ID가 자동으로 생성되므로 ID에 대한 설정자가 없으며 생성자에서도 이를 지정하지 않는다는 것입니다. 그러나 어떤 면 User에서는 여전히 그 클래스가 눈에 띈다 . 그는 자동차 목록을 가지고 있어요! @OneToMany 주석이 목록 위에 나타납니다. 이는 사용자 클래스의 하나의 개체가 여러 컴퓨터에 해당할 수 있음을 의미합니다. "mappedBY" 설정은 클래스의 사용자 필드를 가리킵니다 Auto. 이런 방식으로 기계와 사용자는 서로 연결됩니다. orphanRemoval 설정은 영어에서 "고아 제거"로 매우 잘 번역됩니다. 데이터베이스에서 사용자를 삭제하면 그와 관련된 모든 자동차도 삭제됩니다. 그러면 클래스에서 Auto@ManyToOne 주석(많은 Auto가 하나의 User에 해당할 수 있음) 및 @JoinColumn 주석이 있는 사용자 필드를 볼 수 있습니다. 이는 users 테이블과의 연결이 autos 테이블의 어느 열을 통해 발생하는지를 나타냅니다(앞서 이야기한 것과 동일한 외래 키). 데이터 모델을 만든 후에는 데이터베이스에서 이 데이터에 대한 작업을 수행하도록 프로그램을 가르칠 차례입니다. HibernateSessionFactoryUtil 유틸리티 클래스부터 시작해 보겠습니다. 애플리케이션이 데이터베이스와 작동하도록 세션 팩토리를 생성하는 작업은 단 하나뿐입니다(안녕하세요, "Factory!" 패턴). 그는 다른 어떤 것도 할 수 없습니다.
package utils;

import models.Auto;
import models.User;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactoryUtil {
    private static SessionFactory sessionFactory;

    private HibernateSessionFactoryUtil() {}

    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration().configure();
                configuration.addAnnotatedClass(User.class);
                configuration.addAnnotatedClass(Auto.class);
                StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
                sessionFactory = configuration.buildSessionFactory(builder.build());

            } catch (Exception e) {
                System.out.println("Exception!" + e);
            }
        }
        return sessionFactory;
    }
}
User이 클래스에서는 새로운 구성 객체인 Configuration을 생성하고 엔터티로 인식해야 하는 클래스( 및 ) 를 전달합니다 Auto. 방법에 주의하세요 configuration.getProperties(). 다른 속성은 무엇입니까? 어디? 속성은 hibernate.cfg.xml 특수 파일에 지정된 최대 절전 모드 작동 방식에 대한 매개 변수입니다. 첫 번째 Hibernate 애플리케이션 - 11Hibernate.cfg.xml은 여기에서 읽습니다: new Configuration().configure(); 보시다시피, 그 안에는 특별한 것이 없습니다. 데이터베이스에 연결하기 위한 매개변수와 특별한 매개변수 show_sql이 있습니다. 데이터베이스에 대해 최대 절전 모드로 실행되는 모든 SQL 쿼리가 콘솔에 출력되도록 하는 데 필요합니다. 이런 식으로, 당신은 Hibernate가 매 순간 무엇을 하고 있는지 정확하게 볼 수 있고 "마법" 효과를 제거할 수 있습니다. 다음으로 클래스가 필요합니다 UserDAO. (좋은 의미에서는 인터페이스를 통해 프로그래밍해야 합니다. 인터페이스를 만들고 UserDAO별도로 구현해야 UserDAOImpl하지만, 코드 양을 줄이기 위해 생략하겠습니다. 실제 프로젝트에서는 이 작업을 수행하지 마세요!) DAO(데이터 액세스 개체)는 가장 일반적인 디자인 패턴 중 하나인 "데이터 액세스"입니다. 그 의미는 간단합니다. 애플리케이션에서 데이터 액세스만 담당하고 다른 작업은 수행하지 않는 레이어를 생성하는 것입니다. 데이터베이스에서 데이터를 가져오고, 데이터를 업데이트하고, 데이터를 삭제하면 됩니다. DAO에 대해 자세히 읽어보세요. 업무에 지속적으로 사용하게 될 것입니다. 우리 수업은 무엇을 할 수 있나요 UserDao? 실제로 모든 DAO와 마찬가지로 데이터로만 작동할 수 있습니다. ID로 사용자 찾기, 데이터 업데이트, 삭제, 데이터베이스에서 모든 사용자 목록 가져오기, 데이터베이스에 새 사용자 저장 등이 모든 기능입니다.
package dao;

import models.Auto;
import models.User;
import org.hibernate.Session;
import org.hibernate.Transaction;
import utils.HibernateSessionFactoryUtil;
import java.util.List;

public class UserDao {

    public User findById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id);
    }

    public void save(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.save(user);
        tx1.commit();
        session.close();
    }

    public void update(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.update(user);
        tx1.commit();
        session.close();
    }

    public void delete(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.delete(user);
        tx1.commit();
        session.close();
    }

    public Auto findAutoById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id);
    }

    public List<User> findAll() {
        List<User> users = (List<User>)  HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list();
        return users;
    }
}
방법은 UserDao서로 비슷합니다. 대부분의 경우 세션 팩토리를 사용하여 세션 개체(데이터베이스에 연결하는 세션)를 수신하고, 이 세션 내에서 단일 트랜잭션을 생성하고, 필요한 데이터 변환을 수행하고, 트랜잭션 결과를 데이터베이스에 저장하고 세션을 닫습니다. 보시다시피 방법 자체는 매우 간단합니다. DAO는 우리 애플리케이션의 "핵심"입니다. 그러나 DAO를 직접 생성하지 않고 main(). 모든 로직이 UserService.
package services;

import dao.UserDao;
import models.Auto;
import models.User;

import java.util.List;

public class UserService {

    private UserDao usersDao = new UserDao();

    public UserService() {
    }

    public User findUser(int id) {
        return usersDao.findById(id);
    }

    public void saveUser(User user) {
        usersDao.save(user);
    }

    public void deleteUser(User user) {
        usersDao.delete(user);
    }

    public void updateUser(User user) {
        usersDao.update(user);
    }

    public List<User> findAllUsers() {
        return usersDao.findAll();
    }

    public Auto findAutoById(int id) {
        return usersDao.findAutoById(id);
    }


}
서비스는 비즈니스 로직 실행을 담당하는 애플리케이션의 데이터 계층입니다. 프로그램에서 일부 비즈니스 로직을 수행해야 하는 경우 서비스를 통해 수행합니다. 서비스는 내부에 포함되어 UserDao있으며 해당 메서드에서 DAO 메서드를 호출합니다. 이것은 함수가 중복된 것처럼 보일 수 있지만(dao 객체에서 메소드를 호출하는 것이 아닌 이유), 객체 수가 많고 논리가 복잡하기 때문에 애플리케이션을 레이어로 나누는 것은 큰 이점이 있습니다(이것은 좋은 습관입니다. 이 정보를 기억하세요 미래에 대해 알아보고 "애플리케이션 레이어"에 대해 읽어보세요."). 우리 서비스에서 논리는 간단하지만 실제 프로젝트에서 서비스 메서드에는 한 줄 이상의 코드가 포함됩니다. :) 이제 애플리케이션이 작동하는 데 필요한 모든 것이 있습니다! 메소드에서 그를 위한 사용자와 머신을 생성하고 main(), 서로 연결하고, 데이터베이스에 저장해 봅시다.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        ferrari.setUser(user);
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
    }
}
보시다시피 users 테이블에는 자체 항목이 있고 autos 테이블에는 자체 항목이 있습니다. 첫 번째 Hibernate 애플리케이션 - 13첫 번째 Hibernate 애플리케이션 - 14사용자 이름을 바꿔 보겠습니다. 사용자 테이블을 지우고 코드를 실행해 보겠습니다.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
    }
}
공장! 첫 번째 Hibernate 애플리케이션 - 15사용자를 삭제하면 어떻게 되나요? 사용자 테이블을 지우고(autos가 자동으로 지워짐) 코드를 실행해 보겠습니다.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
        userService.deleteUser(user);
    }
}
그리고 우리 테이블은 완전히 비어 있습니다(콘솔에 주의하세요. Hibernate가 실행한 모든 쿼리가 콘솔에 표시될 것입니다). 응용 프로그램을 가지고 놀면서 모든 기능을 시험해 볼 수 있습니다. 예를 들어, 머신이 있는 사용자를 생성하고, 이를 데이터베이스에 저장하고, 어떤 ID가 할당되어 있는지 확인하고, main()이 ID를 사용하여 데이터베이스에서 사용자를 "풀"하고 콘솔에 해당 머신 목록을 표시하는 방법을 사용해 보세요. . 물론, 우리는 Hibernate 기능의 작은 부분만을 보았습니다. 그 기능은 매우 광범위하며 오랫동안 Java 개발을 위한 업계 표준 중 하나였습니다. 자세히 연구하고 싶다면 이전 기사 중 하나에서 검토한 "Java Persistence API and Hibernate"라는 책을 추천할 수 있습니다. 이 글이 독자들에게 도움이 되었기를 바랍니다. 궁금한 점이 있으시면 댓글로 질문해 주시면 기꺼이 답변해 드리겠습니다 :) 또한 대회에 참가한 작가에게 "좋아요"를 눌러 응원해 주시는 것도 잊지 마세요. 아니면 더 나은 방법은 – “매우 마음에 듭니다” :) 공부에 행운이 있기를 바랍니다!
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION