尝试在 Java 中使用我的第一个数据库连接 - 我收到大量错误,我不知道为什么

Trying to use my first DB connection in Java - I'm getting loads of errors and I don't know why

所以我必须在 Java 中做一个小应用程序 - 我没有它的背景,所以我真的不知道很多事情(语法上)。我正在使用互联网和 intellij 生成一些代码。 (喜欢模特)

程序构建成功,但随后出现这些运行时错误:

Error at initialing DatabaseManager: Exception [EclipseLink-7107] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Error encountered during string decryption.
Internal Exception: java.io.StreamCorruptedException: invalid stream header: BEAD66C6
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager.getTransaction()" because "this.entityManager" is null
    at database.DatabaseConnection.executeTransaction(DatabaseConnection.java:23)
    at database.daos.EchipaDao.create(EchipaDao.java:23)
    at Main.main(Main.java:11)

这是我的代码:

DatabaseConnection.Java

package database;

import java.util.function.Consumer;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class DatabaseConnection {
    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;

    public DatabaseConnection() {
        this.initTransaction();
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public boolean executeTransaction(Consumer<EntityManager> action) {
        EntityTransaction entityTransaction = entityManager.getTransaction();
        try {
            entityTransaction.begin();
            action.accept(entityManager);
            entityTransaction.commit();
        } catch (RuntimeException e) {
            System.err.println("Transaction error: " + e.getLocalizedMessage());
            entityTransaction.rollback();
            return false;
        }
        return true;
    }

    private boolean initTransaction() {
        try {
            entityManagerFactory = Persistence.createEntityManagerFactory("ProiectMipPersistence");
            entityManager = entityManagerFactory.createEntityManager();
        } catch (Exception e) {
            System.err.println("Error at initialing DatabaseManager: " + e.getMessage().toString());
            return false;
        }
        return true;
    }
}

IDao.java

package database.daos;

import java.util.List;

public interface IDao<T> {
    T get(Long id);
    List<T> getAll ();
    void create (T t);
}

EchipaDao.java

package database.daos;

import database.DatabaseConnection;
import database.models.EchipaEntity;

import javax.persistence.TypedQuery;
import java.util.List;

public class EchipaDao implements IDao<EchipaEntity>{
    DatabaseConnection connection = new DatabaseConnection();

    public EchipaEntity get(Long id) {
        return connection.getEntityManager().find(EchipaEntity.class, Long.valueOf(id));
    }

    @Override
    public List<EchipaEntity> getAll() {
        TypedQuery<EchipaEntity> query = connection.getEntityManager().createQuery("SELECT a FROM EchipaEntity a", EchipaEntity.class);
        return query.getResultList();
    }

    public void create(EchipaEntity echipa) {
        connection.executeTransaction(entityManager -> entityManager.persist(echipa));
    }
}

EchipaEntity.java

package database.models;

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

@Entity
@Table(name = "echipa", schema = "public", catalog = "dbfdlur9ijidho")
public class EchipaEntity {
    @Basic
    @Column(name = "nume_echipa", nullable = false, length = -1)
    private String numeEchipa;
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    public String getNumeEchipa() {
        return numeEchipa;
    }

    public void setNumeEchipa(String numeEchipa) {
        this.numeEchipa = numeEchipa;
    }

    public int getId() {
        return id;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EchipaEntity that = (EchipaEntity) o;
        return id == that.id && Objects.equals(numeEchipa, that.numeEchipa);
    }

    @Override
    public int hashCode() {
        return Objects.hash(numeEchipa, id);
    }
}

Main.java

import database.daos.EchipaDao;
import database.models.EchipaEntity;

public class Main {
    public static void main(String[] args) {
        EchipaDao echipaDao = new EchipaDao();
        EchipaEntity echipaEntity = new EchipaEntity();

        echipaEntity.setNumeEchipa("test");

        echipaDao.create(echipaEntity);

        System.out.println("Hello world");
    }
}

我尝试在线搜索(老实说,只搜索第一个,因为我觉得如果我摆脱它,其余的也会消失)- 我找不到任何对我的情况有意义的东西。

那么,为什么会发生这些错误,我该如何解决?

//编辑:

已添加 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>16</source>
                    <target>16</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
    <!-- ECLIPSELINK -->
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>javax.persistence</artifactId>
        <version>2.0.0</version>
    </dependency>
    <!-- POSTGRES -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.3-1102-jdbc41</version>
    </dependency>
</dependencies>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

在堆栈跟踪的末尾,您可以看到问题的根源:

java.io.StreamCorruptedException: invalid stream header: 2666A3B3

虽然有点神秘,但这通常意味着库不兼容。

仔细查看您的依赖项,您使用的是相当新的 eclipselink 版本(2020 年的 2.7.7),以及其他依赖项的相当旧的版本(javax.persistence 2010 年的 2.0.0,以及2014 年的 postgres 9.3)。

如果您转到 eclipselink 2.7.7 maven 页面 (https://mvnrepository.com/artifact/org.eclipse.persistence/eclipselink/2.7.7),您可以看到用于编译它的依赖项是 jakarta.persistence(javax.persistence 的新名称) 2.2.3,从 2019 年开始,这会更有意义。

如果是 Postgress 驱动,你可以在它的文档中看到 (https://jdbc.postgresql.org/download.html) :

Current Version 42.3.1

This is the current version of the driver. Unless you have unusual requirements (running old applications or JVMs), this is the driver you should be using. It supports PostgreSQL 8.2 or newer and requires Java 8 or newer. It contains support for SSL and the javax.sql package.

因此,要整理您的依赖项,请在 pom.xml

中进行以下更改
<dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>jakarta.persistence</artifactId>
        <version>2.2.3</version>
    </dependency>
    <!-- POSTGRES -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.3.1</version>
    </dependency>
</dependencies>

此外,您正在定义 Maven 编译器插件以使用 java 版本 16,但在属性 maven.compiler.xxx 中指向 java 17。它们完全相同,所以要么您指定属性或插件配置。如果您不使用额外的插件配置,我总是会选择属性。 并根据您的 jdk 版本将其设置为 16 或 17(我会使用 17,因为它是最后一个 LTS jdk 版本)

关注此 eclipselink github 项目线程 (https://github.com/eclipse-ee4j/eclipselink/issues/269) jdk 据说在 3.0.0 中添加了 11 支持。

本地测试后更新

这意味着,从理论上讲,使用 2.7.7 你必须使用 jdk 8。但是我只是 运行 你的代码示例正确地使用了 jdk 11。(16和 17 因 Unsupported class file major version 6061.

而失败

即使仅将原始问题中的 JDK 更改为 11 是不够的,由于答案开头提到的库之间的不兼容问题,您会得到 org.postgresql.util.PSQLException: The authentication type 10 is not supported .

更新 更新依赖关系

好的。这很奇怪,但我认为我们已经解决了最后一个问题。除了所有的库兼容性,JDK 版本支持,这是真实的,如果我们更深入地分析 StreamCorruptedException 我们可以看到发生这种情况的确切点:

ValidationException.errorDecryptingPassword(ValidationException.java:901)

谷歌搜索我发现了一个与此相关的问题,我仍在调查根本原因。但是 为什么 会发生,是因为您使用的是 32 个字符长的密码(精确长度)。显然与 UUID 长度(32 个字符)以及 JPA Provider 读取它的方式有关。当我找到更多答案时,我会更新答案,但更改密码长度,你应该摆脱 StreamCorruptedException(我在本地环境中复制了它)

更新进一步调查

此处已报错https://bugs.eclipse.org/bugs/show_bug.cgi?id=569945

要以这种方式失败,密码必须是 32 个字符长(或 32 的倍数)并且由十六进制字符组成。这样 eclipselink 认为它是加密密码并尝试解密它,抛出您收到的异常。