将DAO自动装配到域对象中

sat*_*shi 4 java spring dao spring-mvc autowired

我正在编写一个网站的功能区/成就系统,我必须为我的系统中的每个功能区编写一些逻辑.例如,如果您是第一批注册到该网站的2,000人或者在论坛中发布了1,000个帖子后,您就可以获得一个功能区.这个想法非常类似于stackoverflow的徽章,真的.

因此,每个功能区显然都在数据库中,但它们还需要一些逻辑来确定用户何时获得功能区.

在我编写它的方式,Ribbon是一个简单的抽象类:

@Entity
@Table(name = "ribbon")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "ribbon_type")
public abstract class Ribbon
{
    @Id
    @Column(name = "id", nullable = false, length = 8)
    private int id;

    @Column(name = "title", nullable = false, length = 64)
    private String title;

    public Ribbon()
    {
    }

    public abstract boolean isEarned(User user);

    // ... getters/setters...
}
Run Code Online (Sandbox Code Playgroud)

您可以看到我将继承策略定义为SINGLE_TABLE(因为我必须像50条带一样编码,我不需要为其中任何一条添加额外的列).

现在,将实现一个特定的功能区,例如:

@Entity
public class First2000UsersRibbon extends Ribbon
{
    @Autowired
    @Transient
    private UserHasRibbonDao userHasRibbonDao;

    public First2000UsersRibbon()
    {
        super.setId(1);
        super.setTitle("Between the first 2,000 users who registered to the website");
    }

    @Override
    public boolean isEarned(User user)
    {
        if(!userHasRibbonDao.userHasRibbon(user, this))
        {
            // TODO
            // All the logic to determine whether the user earned the ribbon
            // i.e. check whether the user is between the first 2000 users who registered to the website
            // Other autowired DAOs are needed
        }
        else
        {
            return true;
        }

        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是userHasRibbonDaoisEarned()方法内部为null ,因此NullPointerException抛出a.

我认为将DAO自动装入域对象是错误的,但在本主题中他们告诉我这是正确的方法(域驱动设计).

我在GitHub上分享了一个非常简单的非常简单的例子:https://github.com/MintTwist/TestApp(记得改变/WEB-INF/properties/jdbc.properties中的连接细节并导入test_app.sql脚本)

任何帮助非常感谢.

谢谢!

更新 - 阅读第一个答案,似乎我的方法是完全错误的.考虑到可能有50-70种不同的色带,您如何理想地构建代码?谢谢

Ale*_*nes 6

我并不是说我同意将DAO注入域实例......但是

您可以将DAO连接到域域对象.但是,你必须从春天声明你的域对象在Spring应用上下文,并获得新的实例使用new.确保使用原型范围!您不希望每次都获得相同的单例实例!

实际上,您要实现的逻辑属于一个服务,该服务注入了它所需的DAO.

也许你可以拥有如下服务:

@Service
public class RibbonServiceImpl implements RibbonService

  @Autowired
  private RibbonDAO ribbonDAO;

  public boolean isEarned(Ribbon ribbon, User user) {
   if(!userHasRibbonDao.userHasRibbon(user, this))
        {
            // TODO
            // All the logic to determine whether the user earned the ribbon
            // i.e. check whether the user is between the first 2000 users who registered to the website
            // Other autowired DAOs are needed
        }
        else
        {
            return true;
        }

        return false;
  }  
Run Code Online (Sandbox Code Playgroud)