Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 存储库与DAO(再次)_Spring_Web Services_Server_Abstraction Layer - Fatal编程技术网

Spring 存储库与DAO(再次)

Spring 存储库与DAO(再次),spring,web-services,server,abstraction-layer,Spring,Web Services,Server,Abstraction Layer,一般来说,这个背景故事并不重要,只是为了解释下面的代码: 服务器处理用户和用户组。用户组能够“发现”地点——此时这些地点完全来自GooglePlacesAPI 当前实施 目前,我的服务层中有很多JpaRepository对象,我称之为存储库。我之所以强调“存储库”,是因为在我下面提出的解决方案中,它们将降级为DAOs 然而,我不喜欢我当前的代码,也是我在这里提出问题的原因,是人们在UserGroupService中可以找到的存储库数量 @Service public class UserGr

一般来说,这个背景故事并不重要,只是为了解释下面的代码:

服务器处理用户和用户组。用户组能够“发现”地点——此时这些地点完全来自GooglePlacesAPI


当前实施
目前,我的服务层中有很多
JpaRepository
对象,我称之为存储库。我之所以强调“存储库”,是因为在我下面提出的解决方案中,它们将降级为DAOs

然而,我不喜欢我当前的代码,也是我在这里提出问题的原因,是人们在
UserGroupService
中可以找到的存储库数量

@Service
public class UserGroupService {

    private final static Logger LOGGER = LogManager.getLogger(UserGroupService.class);

    @Autowired
    private UserGroupRepository userGroupRepository;

    @Autowired
    private UserGroupPlaceRepository userGroupPlaceRepository;

    @Autowired
    private PlaceRepository placeRepository;

    @Autowired
    private GooglePlaceRepository googlePlaceRepository;

    @Autowired
    private GooglePlaces googlePlaces;

    public UserGroupService() {
    }

    @Transactional
    public void discoverPlaces(Long groupId) {

        final UserGroup userGroup = this.userGroupRepository.findById(groupId).orElse(null);

        if (userGroup == null) {
            throw new EntityNotFoundException(String.format("User group with id %s not found.", groupId));
        }

        List<PlacesSearchResult> allPlaces = this.googlePlaces.findPlaces(
                userGroup.getLatitude(),
                userGroup.getLongitude(),
                userGroup.getSearchRadius());

        allPlaces.forEach(googlePlaceResult -> {

            GooglePlace googlePlace = this.googlePlaceRepository.findByGooglePlaceId(googlePlaceResult.placeId);

            if (googlePlace != null) {
                return;
            }

            Place place = new Place();
            place.setLatitude(googlePlaceResult.geometry.location.lat);
            place.setLongitude(googlePlaceResult.geometry.location.lng);
            place.setPlaceType(Place.PlaceType.GOOGLE_PLACE);
            place.setName(googlePlaceResult.name);
            place.setVicinity(googlePlaceResult.vicinity);

            place = this.placeRepository.save(place);

            UserGroupPlace.UserGroupPlaceId userGroupPlaceId = new UserGroupPlace.UserGroupPlaceId();
            userGroupPlaceId.setUserGroup(userGroup);
            userGroupPlaceId.setPlace(place);

            UserGroupPlace userGroupPlace = new UserGroupPlace();
            userGroupPlace.setUserGroupPlaceId(userGroupPlaceId);

            this.userGroupPlaceRepository.save(userGroupPlace);

            googlePlace = new GooglePlace();
            googlePlace.setPlace(place);
            googlePlace.setGooglePlaceId(googlePlaceResult.placeId);

            this.googlePlaceRepository.save(googlePlace);
        });
    }
}
但是,这不是一个选项,因为这样我就不能有一个只保存一个位置的
PlaceRepository


我的建议
我想我的困惑始于Spring使用的名称。例如,
jpa positionary
-我不太确定这是否真的是“正确”的名称。因为据我所知,这些对象实际上就像数据访问对象(DAO)一样工作。我认为它实际上应该是这样的:

public interface PlaceDao extends JpaRepository<Place, Long> {
}

public interface GooglePlaceDao extends JpaRepository<Place, Long> {
}

@Repository
public class GooglePlaceRepository {

    @Autowired
    private PlaceDao placeDao;

    @Autowired
    private GooglePlaceDao googlePlaceDao;

    public List<GooglePlace> findByGroupId(Long groupId) {
    // ..
    }

    public void save(GooglePlace googlePlace) {
    // ..
    }

    public void saveAll(List<GooglePlace> googlePlaces) {
    // ..
    }
}

@Service
public class UserGroupService {

    @Autowired
    private GooglePlaceRepository googlePlaceRepository;

    @Autowired
    private UserGroupRepository userGroupRepository;

    @Transactional
    public void discoverPlaces(Long groupId) {

    final UserGroup userGroup = this.userGroupRepository.findById(groupId).orElse(null)
        .orElseThrow(throw new EntityNotFoundException(String.format("User group with id %s not found.", groupId)));


    List<PlacesSearchResult> fetched = this.googlePlaces.findPlaces(
            userGroup.getLatitude(),
            userGroup.getLongitude(),
            userGroup.getSearchRadius());

    // Either do the mapping here or let GooglePlaces return 
    // List<GooglePlace> instead of List<PlacesSearchResult>

    List<GooglePlace> places = fetched.stream().map(googlePlaceResult -> {
        GooglePlace googlePlace = this.googlePlaceRepository.findByGooglePlaceId(googlePlaceResult.placeId);

        if (googlePlace != null) {
            return googlePlace;
        }

        Place place = new Place();
        place.setLatitude(googlePlaceResult.geometry.location.lat);
        place.setLongitude(googlePlaceResult.geometry.location.lng);
        place.setPlaceType(Place.PlaceType.GOOGLE_PLACE);
        place.setName(googlePlaceResult.name);
        place.setVicinity(googlePlaceResult.vicinity);
        googlePlace = new GooglePlace();
        googlePlace.setPlace(place);
        googlePlace.setGooglePlaceId(googlePlaceResult.placeId);
        return googlePlace;
    }).collect(Collectors.toList());

    this.googlePlaceRepository.saveAll(places);        

    // Add places to group..
    }

}
公共接口PlaceDao扩展了JpaRepository{
}
公共接口GooglePlaceDao扩展了JpaRepository{
}
@存储库
公共类GooglePlaceRepository{
@自动连线
私人配售;
@自动连线
私有的GooglePlaceDao GooglePlaceDao;
公共列表findByGroupId(长groupId){
// ..
}
公共作废保存(Google Place Google Place){
// ..
}
public void saveAll(列出googlePlaces){
// ..
}
}
@服务
公共类UserGroupService{
@自动连线
私有GooglePlaceRepository GooglePlaceRepository;
@自动连线
私有UserGroupRepository UserGroupRepository;
@交易的
公共空间发现地点(长groupId){
final UserGroup UserGroup=this.userGroupRepository.findById(groupId).orElse(null)
.OrelsThrow(抛出新EntityNotFoundException(String.format(“未找到id为%s的用户组)”,groupId));
List fetched=this.googlePlaces.findPlaces(
userGroup.getLatitude(),
userGroup.getLongitude(),
userGroup.getSearchRadius());
//要么在这里进行映射,要么让GooglePlaces返回
//列表而不是列表
List places=fetched.stream().map(googlePlaceResult->{
GooglePlace GooglePlace=this.googlePlaceRepository.findByGooglePlaceId(googlePlaceResult.placeId);
if(googlePlace!=null){
返回谷歌广场;
}
地点=新地点();
setLatitude(googlePlaceResult.geometry.location.lat);
setLongitude(googlePlaceResult.geometry.location.lng);
place.setPlaceType(place.PlaceType.GOOGLE_place);
setName(googlePlaceResult.name);
place.setapproach(googlePlaceResult.approach);
googlePlace=新的googlePlace();
googlePlace.setPlace(place);
setGooglePlaceId(googlePlaceResult.placeId);
返回谷歌广场;
}).collect(Collectors.toList());
this.googlePlaceRepository.saveAll(地点);
//将位置添加到组。。
}
}

总结
我想知道我没有看到什么。我是在与框架抗争,还是我的数据模型毫无意义,这就是我发现自己在与框架抗争的原因?还是我对如何使用这两种模式“Repository”和“DAO”还有疑问


如何实现这一点?

我认为foreach在我看来不是一个好方法。仅仅为了一个功能的单一职责,您就做了很多事情。我会把它重构成一个标准的循环

        Place place = new Place();
        place.setLatitude(googlePlaceResult.geometry.location.lat);
        place.setLongitude(googlePlaceResult.geometry.location.lng);
        place.setPlaceType(Place.PlaceType.GOOGLE_PLACE);
        place.setName(googlePlaceResult.name);
        place.setVicinity(googlePlaceResult.vicinity);

        place = this.placeRepository.save(place);
这一部分很容易成为服务中的方法

        UserGroupPlace.UserGroupPlaceId userGroupPlaceId = new 
        UserGroupPlace.UserGroupPlaceId();
        userGroupPlaceId.setUserGroup(userGroup);
        userGroupPlaceId.setPlace(place);

        UserGroupPlace userGroupPlace = new UserGroupPlace();
        userGroupPlace.setUserGroupPlaceId(userGroupPlaceId);

        this.userGroupPlaceRepository.save(userGroupPlace);
那部分也是

        googlePlace = new GooglePlace();
        googlePlace.setPlace(place);
        googlePlace.setGooglePlaceId(googlePlaceResult.placeId);

        this.googlePlaceRepository.save(googlePlace);

这部分:我不明白你为什么这么做。您可以只更新从repo加载的googlePlace实例。Hibernate/事务正在为您完成其余的工作。

我认为您的服务中存在太多的存储库依赖项是正确的。就我个人而言,我尝试将
@Autowired
依赖项的数量保持在最低限度,并且我尝试仅在一个服务中使用存储库,并通过该服务公开其更高级别的功能。在我们公司,我们称之为数据主权(德语:Datenhoheit),其目的是确保在应用程序中只有一个地方可以修改这些实体

根据我从您的代码中了解到的情况,我将介绍一个
places服务
,它与
PlaceRepository
GooglePlaceRepository
GooglePlaces
具有所有依赖关系。如果您觉得服务不是正确的名称,您也可以将其称为
PlacesDao
,用Spring
@组件
注释标记它,并注入所有存储库,这些存储库根据定义是事物的集合

@Component
public class PlacesDao {

    @Autowired
    private PlaceRepository placeRepository;

    @Autowired
    private GooglePlaceRepository googlePlaceRepository;
此服务/DAO可以提供API
findPlacesForGroup(userGroup)
createNewPlace(…)
,从而使for循环更小、更优雅

旁注:您可以将前四行合并为一行。Java选项支持
orelsetrow()
方法:

UserGroup userGroup = userGroupRepository.findById(groupId).orElseThrow(() -> 
     new EntityNotFoundException(String.format("User group with id %s not found.", groupId));

更适合你。嗨!谢谢你的回答。所以问题是:我有不同类型的地方(另一个是
CUSTOM\u-PLACE
(CP))。因此,
UserGroupPlace
可以显示CP和
GOOGLE\u PLACE
(GP)。然而,GP需要额外的信息(
placeId
),这意味着我必须编写一个新的
Place
UserGroupPlace
和一个
GooglePlace
。我可以做的是创建一个
UserGroupGooglePlaceDao
,它包装了功能,并通过确保数据库中正确存储此类位置来处理此类位置。但是,对于这种特殊类型,我还需要一个
UserGroupCustomPlaceDao
UserGroup userGroup = userGroupRepository.findById(groupId).orElseThrow(() -> 
     new EntityNotFoundException(String.format("User group with id %s not found.", groupId));