我正在开发一个“简单”的 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>
文件夹结构