Hibernate 服务Dao模式、DTO和关系数据库

Hibernate 服务Dao模式、DTO和关系数据库,hibernate,jpa,service,dao,dto,Hibernate,Jpa,Service,Dao,Dto,首先,如果这个问题已经得到治疗,我很抱歉,但是我没有找到我想要的。 我正在开发一个ERP,我们正在尝试对代码进行重构。主要的主题是我们目前没有使用任何DAO模式,如果我们需要以不同的方式访问“数据库”,这在将来可能会成为一个问题 简言之,我们的体系结构将以这种模式为目标: Bean或Webservices称之为“事务层”(封装服务,以便某些内容可以通过WS公开并执行其他操作)。该层调用服务,该层将调用其他服务或DAO 1) 实体 我的问题是关于最佳做法: 首先,我们使用Hibernate和JP

首先,如果这个问题已经得到治疗,我很抱歉,但是我没有找到我想要的。 我正在开发一个ERP,我们正在尝试对代码进行重构。主要的主题是我们目前没有使用任何DAO模式,如果我们需要以不同的方式访问“数据库”,这在将来可能会成为一个问题

简言之,我们的体系结构将以这种模式为目标:

Bean或Webservices称之为“事务层”(封装服务,以便某些内容可以通过WS公开并执行其他操作)。该层调用服务,该层将调用其他服务或DAO

1) 实体

我的问题是关于最佳做法:

  • 首先,我们使用Hibernate和JPARepository来管理实体。所以我猜对存储库的调用应该在DAOImpls中完成?我们对数据库进行的查询(即带有连接、选择等的JPAQuery)和投影如何?这样DAO将返回DTO

  • 我们也不确定在哪里使用DTO。在“事务层”中使用DTO和DAOs中使用实体之间的界线应该在哪里?是否应该将数据传递给服务类,然后将实体全部传递给DAO层?或者我们应该只将参数传递给DAO,然后它创建实体本身(问题是它会导致一些巨大的方法签名)

非常感谢,如果需要,请随时提问

  • 在哪里使用DTO
通常,服务方法获取一个DTO作为参数,在其实现中,该DTO被转换/映射为一个实体,该实体被传递到存储库

存储库(或DAO)应该只知道实体,而不是DTO,其他层应该只知道DTO,而不是实体

总之,服务类应该只接受并返回DTO。 这样做是为了将模型及其细节隐藏在持久层之外。例如:

public class ProjectService {
    // The Repository should be an interface and Spring injects your Impl
    @Autowired
    private ProjectRepository projectRepository;

    public void createProject(ProjectDto dto) {
        // We map the Dto into an Entity
        Project project = new Project();
        project.setName(dto.getName);
        project.setDepartment(dto.getDepartment);        

        projectRepository.save(project);
    }

    public ProjectDto findProject(Long id) {
        // Get Project entity
        Project project = projectRepository.findOne(id);
        // Map entity to dto
        ProjectDto dto = new ProjectDto();
        dto.setName(project.getName());
        dto.setDepartment(project.getDepartment());

        return dto;
    }
}
正如您所看到的,将有很多用于将实体映射到dto和viceversa的样板文件。您可以将其封装在只进行转换的方法中,或者更好地使用映射库,如或

是一个如何使用Orika并在需要时将其与Spring集成的示例

  • 关于DAOs和JPA存储库
如果您使用的是SpringDataJPA,您不需要任何DAO,您只需要存储库的接口,可能还需要该接口的实现。如果需要,您可以拥有DAO并在存储库实现中使用它们,但不需要这样做。他们的参考资料中有很好的例子

要执行SQL查询,可以使用
@Query
。当
nativeQuery=true
时,它可以接受JPQL或本机SQL查询。你可以找到更多信息

希望能有所帮助。

当数据跨越“服务/事务层”时,您肯定应该使用DTO模式。我已经就不这样做时出现的一些常见问题以及如何使用Blaze Persistence实体视图有效地实现DTO方法写了一篇文章

也许您想尝试一下,而不是使用Orika或Dozer,因为它还可以提高查询的性能

如果您有SpringDataJPA存储库,您就不应该再需要单独的DAO了

public interface MyObjectDAO {
    void save();
    List<MyObject> findAllObjects();
   // Some other queries
   // ...
}
@Service
public class MyObjectService{
    @Autowired
    MyObjectDAO dao;

    @Autowired
    MyOtherObjectDAO otherDao;

    public void createObject(String arg1Dto, List<MyOtherObjectDto> arg2Dto){
       // How to deal with arg 2 ? 


        MyObject obj = new MyObject();
        obj.setArg1(arg1);
        obj.setArg2(myEntityRepresentingArg2);
        dao.save(obj1);
    }
}
public class{
    // Many many things...

    //Method called from the Beans
    @Transactional(rollbackFor=Exception.class)
    public void serviceCall(SomeDto arguments){
        myObjectServices.createObject(arguments.getArg1(), arguments.getArg2());
    }
}
public class ProjectService {
    // The Repository should be an interface and Spring injects your Impl
    @Autowired
    private ProjectRepository projectRepository;

    public void createProject(ProjectDto dto) {
        // We map the Dto into an Entity
        Project project = new Project();
        project.setName(dto.getName);
        project.setDepartment(dto.getDepartment);        

        projectRepository.save(project);
    }

    public ProjectDto findProject(Long id) {
        // Get Project entity
        Project project = projectRepository.findOne(id);
        // Map entity to dto
        ProjectDto dto = new ProjectDto();
        dto.setName(project.getName());
        dto.setDepartment(project.getDepartment());

        return dto;
    }
}
  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?0", nativeQuery = true)
  User findByEmailAddress(String emailAddress);