TERASOLUNA's JdbcCodeList
is a function to register the result of SQL search from the database as a code list, and I think it is often used.
It's not a big deal with one or two codelists, but when the number of codelists reaches hundreds of classes, the time it takes to start up becomes unbearable.
So I wondered if I could register multiple code lists at once with ʻUNION ALL` as shown below.
SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_ORDERSTATUS'
UNION ALL
SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_HOGE'
ORDER BY code_bean_name, code_id
Since the code list has 1 code list and 1 bean definition, it is necessary to dynamically add the bean definition in order to register multiple code lists.
ʻOrg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessorIt seems that you can add beans dynamically by creating an implementation class for the interface. If you access the DB from the implementation class of this
BeanDefinitionRegistryPostProcessor` and register the Bean of the code list, you can do what you want.
However, when I actually run it, DB access is not good.
Apparently, at the timing when BeanDefinitionRegistryPostProcessor
works, it seems that the placeholder like$ {hogehoge}
of Bean definition is not resolved, and the string before DB connection string etc. is set from the property ($). {hogehoge}
itself) has been taken and it seems that I can not connect well.
If you do not use placeholders in the DataSource definition and describe the connection string etc. directly in the Bean definition, you can make a DB connection, but writing directly in XML is not good.
Therefore, I gave up on completing with only the implementation class of BeanDefinitionRegistryPostProcessor
and divided it into two stages.
The implementation class of BeanDefinitionRegistryPostProcessor
defines only the bean definition of the required code list. (However, the contents of the code list are empty)
Access the DB with another class @PostConstruct
and set the value map in the empty code list.
The implementation image is as follows.
CustomBeanDefinitionRegistryPostProcessor.java
/**
*
*/
package xxxxxx.yyyyyy.zzzzzz.app.welcome;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.terasoluna.gfw.common.codelist.SimpleMapCodeList;
/**
* @author toshio
*
*/
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
private List<String> codeListNames;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (codeListNames != null) {
for (String codeBeanName : codeListNames) {
BeanDefinition beanDefinition = new RootBeanDefinition(SimpleMapCodeList.class);
registry.registerBeanDefinition(codeBeanName, beanDefinition);
}
}
}
/**
* @param codeListNames set codeListNames
*/
public void setCodeListNames(List<String> codeListNames) {
this.codeListNames = codeListNames;
}
}
CustomCodeListLoader.java
/**
*
*/
package xxxxxx.yyyyyy.zzzzzz.app.welcome;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.terasoluna.gfw.common.codelist.SimpleMapCodeList;
/**
* @author toshio
*
*/
public class CustomCodeListLoader {
/**
* Database access information
*/
private JdbcTemplate jdbcTemplate;
@Autowired
private ApplicationContext applicationContext;
/**
* SQL Query to access the database
*/
private String querySql;
private List<String> codeListNames;
/**
*
*/
private String codeNameColumn;
/**
* property that holds the name of the column of the database holding the value part of the codelist
*/
private String valueColumn;
/**
* property that holds the name of the column of the database holding the label part of the codelist
*/
private String labelColumn;
@PostConstruct
public void afterPropertiesSet() {
Map<String, Map<String, String>> allMap = new HashMap<String, Map<String, String>>();
for (String codeName : codeListNames) {
allMap.put(codeName, new LinkedHashMap<String, String>());
}
List<Map<String, Object>> rows = jdbcTemplate.queryForList(querySql);
for (Map<String, Object> row : rows) {
Object codeName = row.get(codeNameColumn);
Object key = row.get(valueColumn);
Object value = row.get(labelColumn);
if (codeName != null && key != null && value != null) {
Map<String, String> map = allMap.get(codeName.toString());
if (map == null) {
map = new LinkedHashMap<String, String>();
}
map.put(key.toString(), value.toString());
allMap.put(codeName.toString(), map);
}
}
for (Entry<String, Map<String, String>> codeEnt : allMap.entrySet()) {
Object codeBean = applicationContext.getBean(codeEnt.getKey());
if (codeBean instanceof SimpleMapCodeList) {
SimpleMapCodeList smc = (SimpleMapCodeList) codeBean;
smc.setMap(codeEnt.getValue());
}
}
}
/**
* Sets JdbcTemplate
* @param jdbcTemplate JdbcTemplate instance for fetching code list records
*/
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* Setter method for labelColumn
* @param labelColumn column name for fetch a code label
*/
public void setLabelColumn(String labelColumn) {
this.labelColumn = labelColumn;
}
/**
* Setter method for valueColumn
* @param valueColumn column name for fetch code value
*/
public void setValueColumn(String valueColumn) {
this.valueColumn = valueColumn;
}
/**
* Setter method for querySql
* @param querySql sql for fetching code list records from database
*/
public void setQuerySql(String querySql) {
this.querySql = querySql;
}
public void setCodeNameColumn(String codeNameColumn) {
this.codeNameColumn = codeNameColumn;
}
/**
* @param codeListNames set codeListNames
*/
public void setCodeListNames(List<String> codeListNames) {
this.codeListNames = codeListNames;
}
}
projectName-codelist.xml
<bean class="xxxxxx.yyyyyy.zzzzzz.app.welcome.CustomBeanDefinitionRegistryPostProcessor">
<property name="codeListNames">
<list>
<value>CL_ORDERSTATUS</value>
<value>CL_HOGE</value>
</list>
</property>
</bean>
<bean class="xxxxxx.yyyyyy.zzzzzz.app.welcome.CustomCodeListLoader">
<property name="querySql">
<value>
SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_ORDERSTATUS'
UNION ALL
SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_HOGE'
ORDER BY code_bean_name, code_id
</value>
</property>
<property name="codeNameColumn" value="code_bean_name"/>
<property name="valueColumn" value="code_id" />
<property name="labelColumn" value="code_name" />
<property name="jdbcTemplate" ref="jdbcTemplateForCodeList" />
<property name="codeListNames">
<list>
<value>CL_ORDERSTATUS</value>
<value>CL_HOGE</value>
</list>
</property>
</bean>
CREATE TABLE t_sample_codes (
code_bean_name varchar(32) not null,
code_id varchar(32) not null,
code_name varchar(256) not null,
primary key (code_bean_name, code_id)
);
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '1', 'Received');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '2', 'Sent');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '3', 'Cancelled');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '1', 'hoge');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '2', 'hogehoge');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '3', 'hogehogehoge');
commit;
Recommended Posts