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中查询成功/失败的日志输出写反,不利于问题排查。
修复方案
- 优先修改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("插入失败"); } }
- 修正UserBean的save方法,复用已初始化的UserOperations实例:
public void save() { // 直接用init方法里已经实例化的userOperations,不要重复new userOperations.insertUser(getKullanici()); // 补充成功/失败后的跳转逻辑即可 }
- 修正@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()+"条记录"); } }
- 可选优化:listUsers方法也改成try-with-resources写法,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Geralt_of_Rivia
相关产品推荐
相关产品推荐

