You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven项目JSF+PostgreSQL用户插入操作不生效,寻求排查方案

问题:Maven项目用户数据插入PostgreSQL失败

相关代码

前端XHTML页面

<ui:composition
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:p="http://primefaces.org/ui" xmlns:f="http://java.sun.com/jsf/core"
        template="../WEB-INF/template/template.xhtml">

  <ui:param name="pageTitle" value="Ekleme Sayfası" />
  <ui:param name="pageDescription" value="Lütfen aşağıdaki kutucuklara sırayla Kullanıcı Adı, Parola ve E-posta giriniz." />

  <ui:define name="content">
    <div class="row">
      <div class="col-md-12">
        <div class="box box-primary">

          <h:form id="kullaniciForm">
            <!--                        <f:facet name="header">-->
            <!--                            <p:outputPanel>-->
            <!--                                <h:outputText value="Search all fields:" />-->
            <!--                                <p:inputText id="globalFilter" onkeyup="propsTable.filter()" style="width:150px" placeholder="Enter keyword"/>-->
            <!--                            </p:outputPanel>-->
            <!--                        </f:facet>-->

            <div class="box-header with-border">
              <h3 class="box-title">Kullanıcı Ekleme Formu : Kullanıcı Adı, Parola, E-posta</h3>
              <div class="box-tools">
                <p:commandButton action="/kullanici-islemleri/index.xhtml"
                                 value="Geri Dön" styleClass="btn btn-sm btn-primary" icon="fa fa-arrow-left" ajax="false" immediate="true" />
                <p:commandButton action="#{userBean.save}"
                                 value="Kaydet" styleClass="btn btn-sm btn-success" icon="fa fa-plus" ajax="false" />
              </div>
            </div>

            <div class="box-body">

                <h:panelGrid columns="3">

                  <p:inputText size="64" id="kullaniciadi" required="true" value="#{userBean.kullanici.username}">
                    <f:validateLength minimum="4" maximum="64" /></p:inputText>

                  <p:inputText size="64" id="parola" required="true" value="#{userBean.kullanici.password}">
                    <f:validateLength minimum="4" maximum="64" /></p:inputText>

                  <p:inputText size="80" id="eposta" required="true" value="#{userBean.kullanici.email}">
                    <f:validateLength minimum="4" maximum="255" /></p:inputText>

                </h:panelGrid>

            </div>

          </h:form>

        </div>
      </div>
    </div>

  </ui:define>

</ui:composition>

实体类Kullanici.java

package com.alper.model.menu;

public class Kullanici {
    private String username;
    private String password;
    private String email;

    public Kullanici()
    {
        this.username = " ";
        this.password = " ";
        this.email = " ";
    }

    public Kullanici(String username, String password, String email)
    {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

业务Bean类UserBean.java

package com.alper.bean.page;

import com.alper.db.UserOperations;
import com.alper.model.menu.Kullanici;
import lombok.Getter;
import lombok.Setter;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import java.util.*;

@ManagedBean
@ViewScoped
@Getter
@Setter
public class UserBean {

    private List<Kullanici> kullanicilar;
    private Kullanici kullanici;
    private UserOperations userOperations;

    @PostConstruct
    public void init() {
        this.userOperations = new UserOperations();
        setKullanicilar(this.userOperations.listUsers());
        // fail ise popup yap hatali diye
        if(this.kullanicilar == null)
        {
            System.out.println("DONE");
        }else {
            System.out.println("FAILED");
        }

    }

    public UserBean() {
        this.kullanici = new Kullanici();
    }

    public void save() {
        UserOperations userOperations = new UserOperations();
        userOperations.insertUser(getKullanici());
        // fail return "/kullanici-islemleri/yeni-kullanici.xhtml" popup yap hatali diye
        // success return "/kullanici-islemleri/index.xhtml";
    }

    public Kullanici getKullanici() {
        return kullanici;
    }

    public void setKullanici(Kullanici kullanici) {
        this.kullanici = kullanici;
    }

    public void setKullanicilar(List<Kullanici> kullanicilar) {
        this.kullanicilar = kullanicilar;
    }
}

数据库操作类UserOperations.java

package com.alper.db;

import com.alper.model.menu.Kullanici;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class UserOperations extends DBConnection{

    private long total_ids = 0;

    public List<Kullanici> listUsers() {
        List<Kullanici> kullaniciList = new ArrayList<>();

        try {
            Class.forName("org.postgresql.Driver");
            Connection connection = DriverManager.getConnection(getUrl(),getUser(),getPassword());
            PreparedStatement preparedStatement = connection.prepareStatement("select * from users");
            preparedStatement.execute();
            ResultSet resultSet = preparedStatement.getResultSet();

            while (resultSet.next()) {
                Kullanici kullanici = new Kullanici();
                kullanici.setUsername(resultSet.getString(2));
                kullanici.setPassword(resultSet.getString(3));
                kullanici.setEmail(resultSet.getString(4));
                kullaniciList.add(kullanici);
            }
            connection.close();

        } catch (Throwable e) {
            e.printStackTrace();
        }
        return kullaniciList;
    }

    public void insertUser(Kullanici kullanici) {
        String username = kullanici.getUsername();
        String password = kullanici.getPassword();
        String email = kullanici.getEmail();
        try {
            Class.forName("org.postgresql.Driver");
            Connection connection = DriverManager.getConnection(getUrl(),getUser(),getPassword());
            this.total_ids += 1;
//            String query = "insert into users (user_id, username, password, email) values (";
//            query += this.total_ids + ",'" + username + "','" + password + "','" + email + "');";
//            PreparedStatement preparedStatement = connection.prepareStatement(query);
//            preparedStatement.executeUpdate();
            PreparedStatement preparedStatement = connection.prepareStatement("insert into users values(?,?,?,?)");
            preparedStatement.setLong(1,this.total_ids);
            preparedStatement.setString(2,username);
            preparedStatement.setString(3,password);
            preparedStatement.setString(4,email);
            preparedStatement.executeUpdate();
            System.out.println("Successful");
            connection.close();

        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("Failed");
        }
    }
}

问题原因

  • 主键生成逻辑错误:UserOperations中的total_ids是实例变量,每次创建新的UserOperations对象都会重置为0,且没有从数据库查询现有最大主键值,插入时大概率触发主键唯一性约束报错。
  • 插入SQL不规范:未指定插入字段名,若数据库表字段顺序和你预设的不一致,会直接插入失败。
  • 资源管理问题:未使用try-with-resources自动回收数据库连接、Statement等资源,连接耗尽会导致操作失败。
  • Bean层逻辑冗余:UserBean的save方法中重复创建UserOperations对象,没有复用初始化阶段已经创建的实例。
  • 日志逻辑错误:@PostConstruct中查询成功/失败的日志输出写反,不利于问题排查。

修复方案

  1. 优先修改PostgreSQL的users表结构,将user_id字段设置为自增主键(使用BIGSERIAL类型),插入时不需要手动传入主键:
public void insertUser(Kullanici kullanici) {
    // 使用try-with-resources自动关闭资源
    try (Connection connection = DriverManager.getConnection(getUrl(),getUser(),getPassword());
         PreparedStatement preparedStatement = connection.prepareStatement("insert into users (username, password, email) values (?,?,?)")) {
        preparedStatement.setString(1,kullanici.getUsername());
        preparedStatement.setString(2,kullanici.getPassword());
        preparedStatement.setString(3,kullanici.getEmail());
        preparedStatement.executeUpdate();
        System.out.println("插入成功");
    } catch (Throwable e) {
        e.printStackTrace();
        System.out.println("插入失败");
    }
}
  1. 修正UserBean的save方法,复用已初始化的UserOperations实例:
public void save() {
    // 直接用init方法里已经实例化的userOperations,不要重复new
    userOperations.insertUser(getKullanici());
    // 补充成功/失败后的跳转逻辑即可
}
  1. 修正@PostConstruct中的日志逻辑,方便排查问题:
@PostConstruct
public void init() {
    this.userOperations = new UserOperations();
    setKullanicilar(this.userOperations.listUsers());
    if(this.kullanicilar == null) {
        System.out.println("查询用户列表失败");
    }else {
        System.out.println("查询用户列表成功,共"+kullanicilar.size()+"条记录");
    }
}
  1. 可选优化:listUsers方法也改成try-with-resources写法,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Geralt_of_Rivia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 23:30:02