1

データベースにクエリを実行して取得したデータから生成された変更不可能なマップを作成する必要があります。スプリングアノテーションを使用してこれを行うには、どうすればよいですか、またはより良い方法はありますか?

I ran into a problem when creating a singleton for my Regions class and then trying to @Autowire in a RegionService to grab the object from the DAO. The problem is that spring can't instantiate the RegionService because it needs to instantiate the static singleton class Regions which needs to get data from the database as shown below in the constructor.

Please see me classes below (I've removed multiple unneeded methods that don't pertain to this question):

public final class Region {
private static final String DEFAULT_SEPERATOR = "-";
private final Integer key;
private final String description;

public Region(Integer pKey, String pDescription) {
    this.key = pKey;
    this.description = pDescription;
}

public Integer getKey() {
    return this.key;
}

public String getValue() {
    return this.description;
}
}

Here is my singleton:

public final class Regions {
private static Regions regionsInstance = null;

@Autowired
private RegionService regionService;

static Map<Integer, Region> regions;

private Regions() {
    final Map<Integer, Region> tempRegions = new HashMap<Integer, Region>();
    for (final Region region : this.regionService.retrieveAll()) {
        tempRegions.put(region.getKey(), region);
    }
    regions = Collections.unmodifiableMap(tempRegions);
}

public static synchronized Regions getRegionsInstance() {
    if (regionsInstance == null) {
        regionsInstance = new Regions();
    }
    return regionsInstance;
}

public Region getRegion(final Integer pKey) {
    return regions.get(pKey);
}

public List<Region> getRegions() {
    return (List<Region>) regions.values();
}
}

My DAO and Service are just interfaces, no need to post those, here are my Impls:

@Service
public class RegionServiceImpl implements RegionService {

@Autowired
private RegionDAO regionDao;

@Override
public List<Region> retrieveAll() {
    return this.regionDao.retrieveAll();
}
}

My DAOImpl (tested and works, just posting to give you the full picture):

@Repository
public class RegionDAOImpl implements RegionDAO {
private static final String SQL_RETRIEVE_REGIONS = "some random SQL";
@Autowired
private JdbcTemplate jdbcTemplate;

@Override
public List<Region> retrieveAll() {
    try {
        return this.jdbcTemplate.query(SQL_RETRIEVE_REGIONS, new ResultSetExtractor<List<Region>>() {
            @Override
            public List<Region> extractData(ResultSet rs) throws SQLException, DataAccessException {
                return RegionDAOImpl.this.mapRegionData(rs);
            }
        });
    } catch (final DataAccessException dae) {
        throw new DaoException("Could not retrieve regionList from database. " + dae);
    }
}

protected final List<Region> mapRegionData(ResultSet rs) throws SQLException {
    final List<Region> regionList = new ArrayList<Region>();
    while (rs.next()) {
        regionList.add(new Region(rs.getInt("REGION_CD"), rs.getString("REGION_TXT")));
    }
    return Collections.unmodifiableList(regionList);
}

}

Then I run my test(I took out unneeded crap):

@..annotated with things you don't need to know
public class RetrieveRegionsTest {
@Autowired
private Regions r;

@Test
public void getAndLogRegion() {

final List<Region> regionDescriptions = new ArrayList<Region>(this.r.getRegions());
    for (final Region region : regionDescriptions) {
        LOGGER.info(region.getValue());
    }
}

はい、私の構成とクラスパスは正しく設定されています。これを別の方法で機能させることができます。これは、私が必要としているRegionsシングルトンにアクセスするだけではありません。これで、Regions シングルトンのRegionServiceで@Autowiredを削除して、 RegionServiceの新しいインスタンスを作成できることがわかりましたが、それではスプリングの @Autowired 機能の目的が無効になります。

考え、アイデア、コメントはありますか?

4

0 に答える 0