返回

Jakarta EE & Wildfly 连接 MySQL 数据库问题排查与解决

mysql

Jakarta EE 应用通过 JPA 和 Wildfly 连接 MySQL 数据库常见问题排查

最近为一个大学项目开发了一个应用,最初创建了三个简单的表(Student、Teacher 和 Subject)。但当我尝试在 Controller servlet 中列出所有 subject 时,网页上却显示了一个错误。 遇到这种连接问题,确实挺让人头疼的, 咱们一块看看咋解决。

一、 问题根源分析

这种情况,问题通常出在这几个地方:

  1. 数据库连接配置错误: persistence.xml 文件中的配置,比如数据源名称、数据库URL、用户名或密码等,可能跟实际情况对不上。
  2. JPA 提供程序问题: 可能没有正确配置或部署 JPA 提供程序(如 Hibernate)。
  3. 实体类映射问题: 实体类 (Entity) 的 @Entity 注解或其他 JPA 注解,可能配置错误或缺失。
  4. 数据库表或字段不存在: 实体类中的数据库表或数据列明和数据库内的不符。
  5. 驱动问题: 数据库驱动程序 (JDBC Driver) 可能没有正确放置或版本不兼容。
  6. Wildfly 配置问题: 数据源可能没有在 Wildfly 中正确配置。
  7. 事务问题: 代码可能需要数据库操作却缺失事务。

二、 解决方案

针对上面列出的问题原因,咱们一个一个排查,并给出解决方案:

1. 检查 persistence.xml 配置

persistence.xml 是 JPA 的核心配置文件。仔细检查以下几点:

  • jta-data-source: 确保 java:/MysqlXADS 这个数据源名称与 Wildfly 中配置的数据源名称完全一致。

  • 数据库连接信息 (隐式): Wildfly 的数据源配置(通常在 standalone.xmldomain.xml 中)包含了数据库的连接信息,例如数据库 URL、用户名、密码。请确保这些信息正确无误。
    比如我的数据源是以下这般.

 <datasource jta="true" jndi-name="java:/MysqlXADS" pool-name="MysqlXADS" 
     enabled="true" use-ccm="true">
     <connection-url>
     jdbc:mysql://localhost:3306/your_database_name?useSSL=false&amp;serverTimezone=UTC
     </connection-url>
     <driver>mysql</driver>
     <security>
     <user-name>your_username</user-name>
     <password>your_password</password>
     </security>
 </datasource>
  <drivers>
         <driver name="mysql" module="com.mysql">
             <xa-datasource-class>com.mysql.cj.jdbc.MysqlXADataSource</xa-datasource-class>
     </driver>
   </drivers>
  • 隐式属性检查 Wildfly 上jta-data-source所对应的数据源配置需要与项目匹配.

    • connection-url:
     jdbc:mysql://localhost:3306/your_database_name?useSSL=false&serverTimezone=UTC
    
    `your_database_name`, 必须换成自己实际的数据库名.
    
    • user-name:和 password修改成自己的数据库账号和密码.

    • <driver>mysql</driver>这里mysql必须与下面<drivers>内注册的数据库name对应,module用于找到对应module.xml。

示例 (假设在 Wildfly 的 standalone.xml 中配置):

(请看上方示例)

进阶:

  • 如果想在 persistence.xml 中直接指定连接属性(不推荐,不利于配置管理),可以添加类似以下的属性:
<properties>
    <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/your_database_name?useSSL=false&amp;serverTimezone=UTC"/>
    <property name="javax.persistence.jdbc.user" value="your_username"/>
    <property name="javax.persistence.jdbc.password" value="your_password"/>
    <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
       <!-- 选用合适版本的 dialect -->
</properties>

2. 确认 JPA 提供程序

Wildfly 默认使用 Hibernate 作为 JPA 提供程序。通常情况下,不需要额外配置。 但假如你遇到了奇奇怪怪的问题, 想排除一下这方面因素:

  1. 检查依赖: 如果你在 pom.xml 中有依赖项, 请确认 pom.xml 中包含了正确的 Hibernate 或 其他 JPA 提供程序 的依赖。 一般来说 Wildfly 会自带, 如果没有,你可以手动添加:

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.6.15.Final</version>  <!-- 请使用兼容你 Wildfly 版本的 Hibernate 版本 -->
       <scope>provided</scope> <!--provided意思是环境自带,防止版本冲突 -->
    </dependency>
      <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
           <version>5.6.15.Final</version>
            <scope>provided</scope>
        </dependency>
    
    
  2. 不要轻易更改JPA 提供程序,Wildfly 本身自带的已经够用了.

3. 检查实体类映射

  • @Entity 注解: 确保你的 Subject 类(以及其他实体类)都有 @Entity 注解。
  • 表名和字段名: 默认情况下,JPA 会使用类名作为表名,字段名作为列名。 如果你的数据库表名或列名与实体类中的不一致,需要使用 @Table@Column 注解进行映射。
    举个例子:

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;

@Entity
@Table(name = "subjects") // 如果表名不是 "Subject",则需要指定
public class Subject {

    @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY) //根据不同主键生成策略选不同方案。
    private Long id;

    @Column(name = "subject_title") // 如果数据库列名不是 "subjectTitle",则需要指定
    private String subjectTitle;

    // 其他字段、getter 和 setter
      public String getSubjectTitle() {
        return subjectTitle;
    }

}

4. 确认数据库表和数据

  • 检查表是否存在: 使用 MySQL 客户端(如 MySQL Workbench、命令行等)连接到数据库,执行 SHOW TABLES; 确认表名是否正确。
  • 检查字段是否存在: 执行 DESCRIBE subjects; (把 subjects 替换成你的表名) 确认表的字段名和类型是否与实体类中的一致。
  • 检查数据: 执行 SELECT * FROM subjects;,看看有没有数据。

5. 确认数据库驱动

  • Wildfly 中的模块: Wildfly 使用模块(modules)来管理 JDBC 驱动。你需要确保 MySQL 驱动的模块已经正确安装。通常情况下,你得手动把驱动放到 modules 里.
    1. WILDFLY_HOME/modules/ 目录下, 手动创建一个目录结构, 以我的版本为例 com/mysql/main
    2. 将 MySQL 的 JDBC 驱动 JAR 文件 (例如 mysql-connector-java-8.0.30.jar) 放到 WILDFLY_HOME/modules/com/mysql/main 目录下。
    3. WILDFLY_HOME/modules/com/mysql/main 目录下, 手动创建创建 module.xml 文件。
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
    <resources>
        <resource-root path="mysql-connector-java-8.0.30.jar"/>
       <!-- 改成你的jar包的名字-->
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
     </dependencies>
</module>
  4.  编辑你的数据源 `standalone.xml` (上文有提到,需要保持配置名和路径的对应.):

  ```xml
 <drivers>
      <driver name="mysql" module="com.mysql">
          <xa-datasource-class>com.mysql.cj.jdbc.MysqlXADataSource</xa-datasource-class>
        </driver>
    </drivers>
 ```

6. 检查 Wildfly 数据源配置

standalone.xml文件中配置好你的数据库和JDBC驱动。

  1. 部署你的应用 如果修改了代码,要记得重新部署你的项目

  2. 重新启动 Wildfly: 在修改了 Wildfly 的配置文件(如 standalone.xml)后,需要重新启动 Wildfly。

7. 确认是否添加了事务管理

JPA 操作(如查询、更新、删除)通常需要在事务中进行。

  1. 检查SubjectService, 它必须是一个受管理的 bean(例如,用 @Stateless 注解):

    
    import jakarta.ejb.Stateless;
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.persistence.TypedQuery;
    import entities.Subject;
    import java.util.List;
    
    @Stateless
    public class SubjectService {
    
      @PersistenceContext(unitName = "tp2jee")
      // 这个单元名称务必和你的 persistence.xml 里的名字一致
      private EntityManager em;
    
        public List<Subject> getAllSubjects() {
              TypedQuery<Subject> query = em.createQuery("SELECT s FROM Subject s", Subject.class);
            return query.getResultList();
        }
    }
    
    

    在 EJB (@Stateless@Stateful) 中, 事务是自动管理的,无需显式地开启或关闭事务.

安全建议

  • 不要把数据库的账号密码直接写在persistence.xml 里, 使用 Wildfly 数据源配置。
  • 对于生产环境,不要使用 root 账户,给每个应用建立一个独立的数据库用户,并设置最小权限原则.
  • useSSL=false 意味着你关闭了SSL加密, 强烈建议在生产环境中打开这个选项,提高数据库传输的安全性!但启用前需要确保 MySQL 服务器端配置了 SSL。

经过上述步骤的逐一排查和修复,你应该能够解决你的 MySQL 连接问题。记得在每次修改后重新部署应用,并查看 Wildfly 的服务器日志(通常在 standalone/log/server.log)以获取更详细的错误信息,这样可以帮助你更快地定位问题。