Hibernate - 主键问题 - 将对象持久化到 mySQL 数据库不起作用

问题描述 投票:0回答:0

我正在开发一个“简单”的 Web 应用程序项目,并使用 Hibernate 处理模型和数据库;特别是这是一个在线块笔记应用程序,所以在数据库中我有一个用户表和一个待办事项表:

CREATE DATABASE IF NOT EXISTS `to-do-app`;
USE `to-do-app`;

CREATE TABLE `user`(
    username    VARCHAR(20)     NOT NULL,
    `password`  VARCHAR(30)     NOT NULL,
    PRIMARY KEY(username)
);

CREATE TABLE todo (
    todo_id     INT         AUTO_INCREMENT,
    user_id     VARCHAR(20),
    content     TEXT,
    done        boolean,
    PRIMARY KEY(todo_id),
    FOREIGN KEY (user_id) REFERENCES `user`(username)
);

问题 当我对处理表的类执行测试时,Java 中的待办事项表出现问题。

以下类是我正在使用的类: TestTodoRepository

import com.example.todoapp.model.TodoRepository;
import com.example.todoapp.model.beans.Todo;
import com.example.todoapp.model.beans.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTodoRepository {
    private static SessionFactory sessionFactory = null;
    private Session session = null;

    @BeforeAll
    static void setupFactory() {
        sessionFactory = TestConfig.setupFactory(Todo.class);
    }

    @BeforeEach
    void setupSession() {
        session = sessionFactory.openSession();
        session.beginTransaction();
    }

    @AfterEach
    void closeSession() {session.getTransaction().commit();}

    @AfterAll
    static void closeFactory() {
        sessionFactory.close();
    }

    @Test
    public void test1AddTodo() {
        TodoRepository todoRepository = new TodoRepository();

        //  Try adding to-do to user that exists
        Todo todo = new Todo("antonino", "Hello World");
        System.out.println("I will add: " + todo);
        Assert.assertTrue(todoRepository.addTodo(todo));

        todoRepository.closeTodoRepository();
    }

    @Test
    public void test2ExistsTodo() {
        TodoRepository todoRepository = new TodoRepository();

        //  Try finding existing to-do
        Todo toDo = new Todo("antonino", "Hello World");
        Assert.assertTrue(todoRepository.existsTodo(toDo));

        //  Try finding not existing to-do


        todoRepository.closeTodoRepository();
    }

    @Test
    public void test3GetTodosForUser() {
        TodoRepository todoRepository = new TodoRepository();

        User test_user = new User("antonino", "antonino");
        Assert.assertNotNull(todoRepository.getTodosForUser(test_user));

        todoRepository.closeTodoRepository();
    }


}

待办事项

package com.example.todoapp.model.beans;

import jakarta.persistence.*;
import lombok.*;

@Entity(name = "todo")
@Getter
@Setter
@NoArgsConstructor
@ToString
public class Todo {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name = "todo_id")
    private Long id;

    @Column(name = "user_id")
    /*@ManyToOne(cascade = CascadeType.PERSIST)*/
    private String user_id;

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

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

    public Todo(String user_id, String content) {
        this.user_id = user_id;
        this.content = content;
        this.done = false;
    }
}

TodoRepository

package com.example.todoapp.model;

import com.example.todoapp.model.beans.Todo;
import com.example.todoapp.model.beans.User;
import jakarta.persistence.*;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;


import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

public class TodoRepository extends Repository{

    public TodoRepository() {super();}

    /**
     * Add a to-do to the database, used to register new users
     * @param todo: the to-do entity
     * */
    public boolean addTodo(Todo todo) {
        //  if to-do exists can't add a new one
        if (em.find(Todo.class, todo.getId()) != null)
            return false;

        try {
            em.getTransaction().begin();
            em.persist(todo);
            em.getTransaction().commit();
        } catch (EntityExistsException ex) { return false; }
        return true;
    }

    /**
     * Checks if a to-do exists in a database
     * @param todo : contains credentials to test
     * */
    public boolean existsTodo(Todo todo) {
        return em.find(Todo.class, todo.getId()) != null;
    }

    /**
     * WORK IN PROGRESS
     * Gets to-do list based on user id (username)
     * @param user : the owning the to-do
     * */
    public
    List<Todo> getTodosForUser(User user) {
        List<Todo> toDos;

        try {
            Query findToDos = em.createNativeQuery("SELECT * FROM todo WHERE todo.user_id = :user_id");
            findToDos.setParameter("user_id", user.getUsername());

            toDos = (List<Todo>) findToDos.getResultList();
            for(Todo t : toDos)
                System.out.println(t);

            return toDos;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public void closeTodoRepository() {
        super.closeEntityManager();
        super.closeEntityManagerFactory();
    }
}

存储库

package com.example.todoapp.model;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

/**
 * Abstract class that represents a repository of a database entity
 * */
public abstract class Repository {
    protected final EntityManager em;
    protected final EntityManagerFactory emf;

    public Repository() {
        this.emf = Persistence.createEntityManagerFactory("to-do-app");
        this.em = emf.createEntityManager();
    }

    protected void closeEntityManager() {
        em.close();
    }

    protected void closeEntityManagerFactory() {
        emf.close();
    }
}

我认为还需要以下配置文件: Todo.hbm.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- name:full path to class:-->
    <!-- table: table name: (can be omitted. Use the class name as the table name.)-->
    <class name="com.example.todoapp.model.beans.Todo" table="todo">
        <!--Primary key-->
        <id name="id" type="java.lang.Long" column="todo_id"></id>

        <!-- Attributes -->
        <property name="user_id" column="user_id" type="java.lang.String"/>
        <property name="content" column="content" type="java.lang.String"/>
        <property name="done" column="done" type="java.lang.Boolean"/>
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- jdbc driver -->
        <property name="connection.url">jdbc:mysql://localhost:3306/to-do-app</property>
        <!-- database url -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="hibernate.connection.username">myroot</property>
        <property name="hibernate.connection.password">mypassword</property>


        <!-- Load map file -->
        <mapping resource="com/example/todoapp/model/beans/config/User.hbm.xml"/>
        <mapping resource="com/example/todoapp/model/beans/config/Todo.hbm.xml"/>

    </session-factory>
</hibernate-configuration>

persistence.xml

<persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
    <persistence-unit name="to-do-app">
        <!-- Implementation for JPA Provider -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <!-- persistence properties configuration -->
        <properties>
            <!-- jdbc driver -->
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <!-- database url -->
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/to-do-app"/>
            <!-- database username -->
            <property name="jakarta.persistence.jdbc.user" value="myroot"/>
            <!-- database password -->
            <property name="jakarta.persistence.jdbc.password" value="mypassword"/>
            
            <!-- other properties -->
            <!--Print sql statement-->
            <property name="hibernate.show_sql" value = "false" />
            <!--Format sql-->
            <property name="hibernate.format_sql" value = "true" />

        </properties>
    </persistence-unit>
</persistence>

文件夹结构

java hibernate jpa web-development-server
© www.soinside.com 2019 - 2024. All rights reserved.