基于Hibernate ORM的HQL实现报错排查:空指针异常与Autowired静态字段注入问题
Let's tackle each of your problems one by one, starting with the most critical injection errors and NPE, then moving to the broken HQL save logic.
1. Resolve @Autowired Static Field Error & NullPointerException
Root Causes
- Spring doesn’t support @Autowired on static fields: Static fields belong to the class, not an instance of the bean, so Spring can’t inject dependencies into them. Your
hibernateUtilModelstatic field is triggering the first error. - Syntax typo in HibernateUtilModel: The
@Valueforddl-autohas a missing opening brace ($spring.jpa.hibernate.ddl-auto}instead of${spring.jpa.hibernate.ddl-auto}), so this property fails to inject correctly. - Uninitialized dependency in static method: Your
getSessionFactory()static method tries to use an uninitializedhibernateUtilModel, leading to the NullPointerException.
Fixes
Step 1: Correct the @Value Typo in HibernateUtilModel
@Data @AllArgsConstructor @NoArgsConstructor @Service public class HibernateUtilModel { // ... other properties ... // Fix the missing '{' in the annotation @Value("${spring.jpa.hibernate.ddl-auto}") private String update; }
Step 2: Rewrite HibernateUtil for Spring Compatibility
Remove static modifiers and use Spring's lifecycle hooks to initialize the SessionFactory properly:
package com.product.DAO; import java.util.Properties; import com.product.Entity.Product; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.service.ServiceRegistry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class HibernateUtil { // Remove static modifier to allow Spring injection @Autowired private HibernateUtilModel hibernateUtilModel; private SessionFactory sessionFactory; // Initialize SessionFactory once the bean is created @PostConstruct public void initSessionFactory() { if (sessionFactory == null) { try { Configuration configuration = new Configuration(); Properties settings = new Properties(); settings.put(Environment.DRIVER, hibernateUtilModel.getDriver()); settings.put(Environment.URL, hibernateUtilModel.getUrl()); settings.put(Environment.USER, hibernateUtilModel.getUser()); settings.put(Environment.PASS, hibernateUtilModel.getPass()); settings.put(Environment.DIALECT, hibernateUtilModel.getDialect()); settings.put(Environment.SHOW_SQL, hibernateUtilModel.getShow_sql()); settings.put(Environment.IMPLICIT_NAMING_STRATEGY,hibernateUtilModel.getIMPLICIT()); settings.put(Environment.PHYSICAL_NAMING_STRATEGY,hibernateUtilModel.getPHYSICAL()); settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread"); settings.put(Environment.HBM2DDL_AUTO, hibernateUtilModel.getUpdate()); configuration.setProperties(settings); configuration.addAnnotatedClass(Product.class); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()).build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } catch (Exception e) { e.printStackTrace(); } } } // Make this a non-static method public SessionFactory getSessionFactory() { return sessionFactory; } }
Step 3: Inject HibernateUtil into Your DAO
Instead of calling static methods, inject the Spring-managed HibernateUtil bean into your DAO:
@Repository // Use @Repository for DAOs to enable Spring's exception translation public class ProductDAOImpl implements ProductDAO { @Autowired private HibernateUtil hibernateUtil; // ... rest of your DAO methods ... }
2. Fix the HQL Save Logic
Root Cause
Your current save method uses an INSERT...SELECT HQL query, which copies existing Product records instead of saving the new product parameter. This is not the intended behavior for a save operation, and the redundant call to saveStudent adds unnecessary complexity.
Fix: Simplify the Save Method
Replace the broken logic with a clean implementation that uses Hibernate's core session methods:
@Override public Product save(Product product) { Transaction transaction = null; try (Session session = hibernateUtil.getSessionFactory().openSession()) { transaction = session.beginTransaction(); // Save the new product and get its generated primary key Serializable savedId = session.save(product); // Optional: Fetch the persisted entity (save already updates the product's ID) Product savedProduct = session.get(Product.class, savedId); transaction.commit(); return savedProduct != null ? savedProduct : product; } catch (Exception e) { if (transaction != null) { transaction.rollback(); } e.printStackTrace(); // Throw a custom exception instead of returning a potentially invalid product throw new RuntimeException("Failed to save product", e); } }
Why This Works
session.save(product)persists the new entity and updates theproductobject'spurchase_item(primary key) with the generated value.- The try-with-resources block automatically closes the session, so no manual
session.close()is needed. - Transactions are handled properly, rolling back on failure and committing on success.
3. Bonus: Use Spring Boot's Built-in Hibernate Support
In Spring Boot, you don’t need a custom HibernateUtil at all! Spring auto-configures a SessionFactory via EntityManagerFactory. Simplify your DAO by injecting EntityManager directly:
@Repository public class ProductDAOImpl implements ProductDAO { @PersistenceContext private EntityManager entityManager; @Override public Product save(Product product) { Session session = entityManager.unwrap(Session.class); Transaction transaction = session.beginTransaction(); try { session.save(product); transaction.commit(); return product; } catch (Exception e) { transaction.rollback(); throw new RuntimeException("Failed to save product", e); } } }
This eliminates the need for HibernateUtil and HibernateUtilModel entirely, as Spring Boot handles all Hibernate configuration from your application.yaml.
内容的提问来源于stack exchange,提问作者SpicySandwich

