>

내 프로젝트에는 Store 클래스가 있고 Manager 클래스도 있습니다. 이제 관리자는 많은 상점을 관리 할 수 ​​있지만, 상점에는 하나의 관리자가있을 수 있습니다. 결과는 다음과 같습니다.

관리자 등급이 있습니다 : ArrayList 상점;

상점 등급이 있습니다 : 관리자 매니저;

상점에서 관리자를 참조 할 수 있어야하지만 관리자로부터 모든 상점을 가져와야합니다.

그래서 할 수 있어야합니다. manager.getStores (); & store.getManager ();

이것은 새로운 객체 인스턴스를 만드는주기를 만들고 데이터베이스에서 계속 읽을 필요가 있습니다. 나는 디자인과 실용적인 관점 에서이 문제를 해결하는 방법을 잘 모르겠습니다. 아직도 여전히 새로운 사람이므로 누군가 나를 도울 수 있다면 놀랍습니다!

  • 답변 # 1

    이 예에서는 managers 테이블에 ID 가 있다고 가정합니다.  기본 키 및 저장 테이블에 manager 가 있습니다  관리자 ID 를 참조하는 필드 .

    그래서 SELECT  당신의 managers  DB의 데이터, 레코드를 반복하고 managers 를 빌드하십시오.  객체 배열.

    다음 SELECT  당신의 stores 에서  테이블, 그 레코드를 통해 루프는 당신의 stores 구축을 시작합니다  객체 배열을 사용하면이 루프에서 중첩 된 루프를 사용하여 관리자 배열을 통해 상점 객체/레코드가 참조한 관리자를 찾은 다음 해당 관리자를 상점에 설정하고 상점을 관리자의 상점 목록에 추가 할 수 있습니다.

    //  Assume db_mgrs and db_stores are result sets return from database.
    Object[][] db_mgrs = new Object[][]{{0, "Steve"}, {1, "Bob"}, {2, "Nick"}, {3, "Sam"}};
    Object[][] db_stores = new Object[][]{{1, "First Store", 0}, {2, "Second Store", 0}, {3, "Third Store", 2}};
    ArrayList<Manager> managers = new ArrayList<>();
    ArrayList<Store> stores = new ArrayList<>();
    for(int i = 0; i < db_mgrs.length; i++) {
        managers.add(new Manager((int)db_mgrs[i][0], (String)db_mgrs[i][1]));
    }
    for(int i = 0; i < db_stores.length; i++) {
        stores.add(new Store((int)db_stores[i][0], (String)db_stores[i][1]));
        for(int j = 0; j < managers.size(); j++) {
            if(db_stores[i][2].equals(managers.get(j).getId())) {
                stores.get(i).setMgr(managers.get(j));
                break;
            }
        }
    }
    for(int i = 0; i < stores.size(); i++) {
        System.out.println(stores.get(i).getMgrName());
    }
    
    

  • 답변 # 2

    성능을 위해 참조를 양방향으로 저장해야하는 이유는 단 하나입니다. 많은 데이터를 저장 및 검색해야하는 경우가 아니라면 최대한 간단하게 유지하십시오.

    class Store {
        private Manager manager;
        public Manager hasManager(Manager manager) {
            return this.manager.equals(manager);
        }
    }
    class StoreList {
        private final List<Store> stores;
        public Stream<Store> getManagedStores(Manager manager) {
            return stores.stream().filter(s -> s.hasManager(manager));
        }
    } 
    
    

    상점은 한 명의 관리자 만 가질 수 있으므로 참조 무결성이 자동으로 적용됩니다. 관리자가 아닌 상점 목록에서 상점 관리에 대한 논리를 캡슐화합니다. 이것에 대한 좋은 점은 Manager 클래스가 상점에 대해 전혀 알 필요가 없다는 것입니다. 동일한 클래스를 변경하지 않고 식당을 관리하는 데 사용할 수 있습니다.

    정말로 getStores 가 필요한 경우   Manager 에서  클래스를 확인하면 몇 가지 유효성 검사를 구현해야합니다.

    class StoreList {
        public boolean hasStore(Store store) {
            return stores.contains(store);
        }
    }
    class Manager {
        private final StoreList stores;
        public boolean hasStoreInStoreList(Store store) {
            return stores.hasStore(store);
        }
        public Stream<Store> getStores() {
            return stores.getManagedStores(this);
        }
    }
    class Store {
        public void setManager(Manager manager) {
            if (manager.hasStoreInStoreList(this))
                this.manager = manager;
            else
                throw new IllegalArgumentException("Manager for different stores");
        }
    }
    
    

    성능이 중요한 경우 일반적인 접근 방식은 캐시를 사용하는 것입니다. 검색을 반복하지 않아도되도록 검색 결과 사본을 유지하는 것과 관련하여 잘 알려진 디자인 패턴입니다. 검색이 다시 실행되도록 참조가 변경되면 캐시가 제거됩니다. 다음과 같이 보일 수 있습니다 :

    class Manager {
        private Optional<List<Store>> managedStores = Optional.empty();
        public void purgeCache() {
            managedStores = Optional.empty();
        }
        public Stream<Store> getStores() {
            if (!managedStores.isPresent())
                managedStores = Optional.of(stores.getManagedStores(this)
                    .collect(Collectors.toList()));
            return managedStores.get().stream();
        }
    }
    class Store {
        public void setManager(Manager manager) {
            if (!manager.equals(this.manager)) {
                this.manager.purgeCache();
                this.manager = manager;
                this.manager.purgeCache();
            }
        }
    }
    
    

    마지막으로, 실제로 양방향으로 참조를 유지하려면 다른 방향으로 참조를 자동으로 변경하려면 각 업데이트가 필요합니다. 이것은 악명 높은 오류 접근 방식입니다. 모델이 복잡해지면 참조 손상이 쉽게 감지되지 않습니다 (예 : 수퍼 클래스의 setter를 호출하지 않고 setter를 재정의하는 하위 클래스를 통해). 가능하다면 이것을 피하십시오.

  • 답변 # 3

    이 디자인 (또는 스키마에 따라 변형)을 사용하여 양방향 매핑을 만들 수 있습니다 :

    Store.class

    public class Store {
        private Manager manager;
        private final String storeName;
        public Store(String storeName) {
            this.storeName = storeName;
        }
        public void setManager(Manager manager) {
            this.manager = manager;
        }
        public Manager getManager() {
            return manager;
        }
        public String getStoreName() {
            return storeName;
        }
    }
    
    

    Manager.class

    import java.util.ArrayList;
    import java.util.List;
    public class Manager {
        private List<Store> stores;
        private final String firstName;
        private final String lastName;
        public Manager(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String getFirstName() {
            return firstName;
        }
        public String getLastName() {
            return lastName;
        }
        public List<Store> getStores() {
            return stores;
        }
        public void assignStore(Store store) {
            if (stores == null) {
                stores = new ArrayList<>();
            }
            stores.add(store);
        }
        public String getFullName() {
            return firstName + " " + lastName;
        }
    }
    
    

    RetailCorp.class (매핑 작성) :

    import java.util.ArrayList;
    import java.util.List;
    public class RetailCorp {
        public static void main(String[] args) {
            //This is simulating list of managers from a data store
            List<Manager> managerList = getManagerData();
            //This is simulating list of stores from a data store. Each store has a manager assigned to it.
            List<Store> storeList = getStoreData(managerList);
            System.out.println("=== Now, look through each store and assign managers their list of stores");
            for (int i = 0; i < storeList.size(); i++) {
                Store currentStore = storeList.get(i);
                currentStore.getManager().assignStore(currentStore);
            }
            //Output stores and their managers
            showStoresAndTheirManagers(storeList);
            //Output managers and their stores
            showManagersAndTheirStores(managerList);
        }
        private static List<Manager> getManagerData() {
            System.out.println("=== Building manager data");
            List<Manager> managerList = new ArrayList<>();
            int totalManagers = 2;
            for (int i = 0; i < totalManagers; i++) {
                managerList.add(new Manager("FN-" + i, "LN-" + i));
            }
            return managerList;
        }
        private static List<Store> getStoreData(List<Manager> managerList) {
            System.out.println("=== Building stores data");
            List<Store> storeList = new ArrayList<>();
            int totalStores = 3;
            for (int i = 0; i < totalStores; i++) {
                storeList.add(new Store("Store " + i));
            }
            storeList.get(0).setManager(managerList.get(0));    //store 0 -> manager 0
            storeList.get(1).setManager(managerList.get(1));    //store 1 -> manager 1
            storeList.get(2).setManager(managerList.get(0));    //store 2 -> manager 0
            return storeList;
        }
        private static void showStoresAndTheirManagers(List<Store> storeList) {
            System.out.println("=== Print stores and their manager");
            for (int i = 0; i < storeList.size(); i++) {
                Store currentStore = storeList.get(i);
                System.out.println(currentStore.getStoreName() + " has Manager: " + currentStore.getManager().getFullName());
            }
        }
        private static void showManagersAndTheirStores(List<Manager> managerList) {
            System.out.println("=== Print managers and their stores");
            for (int i = 0; i < managerList.size(); i++) {
                Manager currentManager = managerList.get(i);
                System.out.println("Manager: " + currentManager.getFullName() + " has total " + currentManager.getStores().size() + " stores");
                currentManager.getStores().forEach(s -> System.out.println(s.getStoreName()));
            }
        }
    }
    
    

    출력 실행

    === Building manager data
    === Building stores data
    === Now, look through each store and assign managers their list of stores
    === Print stores and their manager
    Store 0 has Manager: FN-0 LN-0
    Store 1 has Manager: FN-1 LN-1
    Store 2 has Manager: FN-0 LN-0
    === Print managers and their stores
    Manager: FN-0 LN-0 has total 2 stores
    Store 0
    Store 2
    Manager: FN-1 LN-1 has total 1 stores
    Store 1
    
    

  • 이전 트위터 API 및 사용자 정보 얻기 PHP
  • 다음 sql - sqlalchemy - csv를 사전으로 변환 한 후 sqlite 테이블에 클래스 값이 채워지지 않음