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

请教:我的MysqlDAOFactory单例模式实现是否正确?

你的MysqlDAOFactory单例实现问题分析及修正建议

当前实现的核心问题

  1. 线程不安全:connection()方法的懒加载逻辑没有同步控制,多线程环境下会有多个线程同时进入if(f == null)分支,导致创建多个MysqlDAOFactory实例,违背单例设计的初衷。
  2. EntityManager线程安全风险:EntityManager本身不是线程安全的,你把同一个em实例传递给所有PlaneDAOImpl,当多个线程同时调用DAO方法时,会引发并发访问异常。
  3. 冗余的@Autowired注解:这个类是通过new关键字手动实例化的,不属于Spring容器管理对象,@Autowired注解不会生效,完全可以移除。
  4. 单例初始化隐患:静态变量f没有用volatile修饰,可能因JVM指令重排导致其他线程读取到半初始化的实例。

修正后的实现方案

方案1:双重检查锁(DCL)实现线程安全单例,修复EntityManager问题

public class MysqlDAOFactory {
    // 用volatile禁止指令重排,避免半初始化实例被读取
    private static volatile MysqlDAOFactory instance;
    // EntityManagerFactory是线程安全的,作为单例持有
    private final EntityManagerFactory emf;

    private MysqlDAOFactory() {
        Persistence.generateSchema("jpa", null);
        emf = Persistence.createEntityManagerFactory("jpa");
    }

    public static MysqlDAOFactory getInstance() {
        if (instance == null) {
            synchronized (MysqlDAOFactory.class) {
                if (instance == null) {
                    instance = new MysqlDAOFactory();
                }
            }
        }
        return instance;
    }

    public PlaneDAO getPlaneDAOImpl() {
        // 每次获取DAO时创建新的EntityManager,避免线程安全问题
        EntityManager em = emf.createEntityManager();
        return new PlaneDAOImpl(em);
    }
}

方案2:枚举单例(简洁且安全,推荐)

枚举单例天然线程安全,还能防止反射破坏单例特性,同时处理EntityManager的线程安全问题:

public enum MysqlDAOFactory {
    INSTANCE;

    private final EntityManagerFactory emf;

    MysqlDAOFactory() {
        Persistence.generateSchema("jpa", null);
        emf = Persistence.createEntityManagerFactory("jpa");
    }

    public PlaneDAO getPlaneDAOImpl() {
        EntityManager em = emf.createEntityManager();
        return new PlaneDAOImpl(em);
    }
}

使用时直接调用MysqlDAOFactory.INSTANCE.getPlaneDAOImpl()即可。

额外建议

如果你的项目已经集成Spring,更推荐让Spring管理DAO和EntityManager的生命周期:

  • 给PlaneDAOImpl添加@Repository注解,用@PersistenceContext注入EntityManager
  • 直接通过Spring容器获取DAO实例,无需手动实现DAO工厂,简化代码同时避免单例管理的麻烦

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:27:11