2016-04-03 14 views
1

私は春のブートとspring jdbcテンプレートを使用しています。私はどちらかのプロパティまたはymlファイルでSQLクエリを外部化したい。私はjavaリポジトリクラスにSQLクエリを格納したくない。springブートjdbcリポジトリのプロパティまたはymlファイルからSQLクエリを格納および読み込む方法は?

このケースを処理する最善の方法は何ですか?

これは私のリポジトリクラスが今見ているところです。

@Repository 
public class UserRepositoryImpl extends BaseRepository implements UserRepository { 

    @Override 
    public List<User> findAll(){ 
     String sqlQuery = "SELECT * FROM users"; 
     return jdbcTemplate.query(sqlQuery, userMapper); 
    } 

    @Override 
    public User findById(Long userId){ 
     String sqlQuery = "SELECT * FROM users WHERE id = :userId"; 
     Map<String, String> namedParameters = new HashMap<String, String>(); 
     namedParameters.put("userId", String.valueOf(userId)); 
     return jdbcTemplate.queryForObject(sqlQuery, namedParameters, userMapper); 
    } 
+1

あなたはこのために良い解決策を見つけましたか? – andre3wap

+0

@ andre3wap Nope。まだありません – ashishjmeshram

+0

私は同じことをしたいです。良い解決策を見つけましたか? – Thirumal

答えて

0

私はこれが直接あなたがプロパティファイルまたはYMLについて尋ねるどのように対処していませんが、私はプロジェクト内のSQL文を管理するための最良の方法について尋ねると、一般的にあなたの質問を解釈知っています。非常に多くのSQLコードを持つプロジェクトで作業していたので、私はMyBatisがあまりにも多くの苦情を犯さずに済むことに気付きました。簡単に言えば、外部化SQLから外部XMLファイルへの外部処理は既に処理されており、より多くのSQLを蓄積する際に、ファイル内のsqlの管理性を良好なレベルに保つことができます。

設定するには、基本的にBeanを設定し、2つのmybatis xmlファイルを作成し、リポジトリ用のJavaインターフェイスを作成する必要があります。

public class User { 

    private Long id; 
    private String name; 

... 
} 

public interface UserRepository { 

    List<User> findAll(); 

    User findById(@Param("id") Long userId); 

} 

@Paramは、SQL

META-INF /レポ/ SQLで#{ID}の式に 'ID' 値をマッピングします:あなたの例を取ると、ここでは、ユーザリポジトリのMyBatisのです/userMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<mapper namespace="com.bushcoder.so.app.user.UserRepository"> 

    <resultMap id="user" type="com.bushcoder.so.app.user.User"> 
     <id property="id" column="userId"/> 
     <result property="name" column="name"/> 
    </resultMap> 

    <select id="findAll" resultMap="user"> 
     SELECT id, name FROM user 
    </select> 

    <select id="findById" parameterType="long" resultMap="user"> 
     SELECT id, name FROM user WHERE id = #{id} 
    </select> 

</mapper> 

注:#

META-INF /レポ/ SQL/SQLMAP-config.xmlがuserRepository.findByIdへの呼び出しを介して渡された値を供給される{ID}。

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE configuration PUBLIC "-//www.mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > 
<configuration> 

    <mappers> 
     <mapper resource="META-INF/repo/sql/userMapper.xml"/> 
    </mappers> 

</configuration> 

「META-INF/repo/sql/sqlmap-config.xml」パスは、Java設定でmybatisに必要なBeanを設定するために使用されます。したがって、設定には4つのBean、つまりsqlSessionFactory、sqlSessionTemplate、dataSource、およびuserRepositoryが必要です。これらはSpringの処理クラスのどこかにある必要があります。私のプロトタイププロジェクトで

@Bean 
    public SqlSessionFactory sqlSessionFactory() throws Exception { 
    SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean(); 
    sqlSessionFactory.setDataSource(dataSource()); 
    sqlSessionFactory.setConfigLocation(new ClassPathResource("META-INF/repo/sql/sqlmap-config.xml")); 
    return sqlSessionFactory.getObject(); 
    } 

    @Bean 
    public SqlSessionTemplate sqlSessionTemplate() throws Exception { 
    return new SqlSessionTemplate(sqlSessionFactory()); 
    } 

    @Bean 
    public DataSource dataSource() { 
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 
    EmbeddedDatabase db = builder 
     .setType(EmbeddedDatabaseType.H2) 
     .addScript("META-INF/repo/db/ddl/create-database-script.sql") 
     .addScript("META-INF/repo/db/dml/database-seeder-script.sql") 
     .build(); 
    return db; 
    } 

    @Bean 
    public UserRepository userRepository() throws Exception { 
    return sqlSessionTemplate().getMapper(UserRepository.class); 
    } 

私はH2データベースに行って、スキーマとシードデータの世話をするためにEmbeddedDatabaseBuilderを使用しています。

META-INF /レポ/ DB/DDL /作成、データベースscript.sql:

CREATE TABLE if NOT EXISTS user (
    id INTEGER PRIMARY KEY, 
    name VARCHAR(30) 
); 

META-INF /レポ/ DB/DML /データベースシーダー-script.sql:

INSERT INTO user (id, name) VALUES (1, 'BOB'); 
INSERT INTO user (id, name) VALUES (2, 'LARRY'); 
INSERT INTO user (id, name) VALUES (3, 'FRANK'); 
INSERT INTO user (id, name) VALUES (4, 'CHARLIE'); 
INSERT INTO user (id, name) VALUES (5, 'GARRY'); 

あなたはおそらく、リポジトリをサービスに結び付けます。あなたはより多くのSQLを蓄積し始めると、あなたは新しいリポジトリのインターフェース、そのマッチングマッパーファイルを作成し、今

@SpringBootApplication 
@Import (AppConfig.class) 
public class MybatisConfigExampleApplication { 

    public static void main(String[] args) { 
     ConfigurableApplicationContext context = SpringApplication.run(MybatisConfigExampleApplication.class, args); 

     final UserService users = (UserService) context.getBean("userServiceImpl"); 

     final List<User> allUsers = users.findAll(); 
     System.out.println("allUsers = " + allUsers); 

     final User userById_5 = users.findById(5L); 
     System.out.println("userById_5 = " + userById_5); 
    } 
} 

:呼び出し元のコードは、このようなことができ

public interface UserService { 

    List<User> findAll(); 

    User findById(Long userId); 

} 

@Service 
public class UserServiceImpl implements UserService { 

    @Inject 
    private UserRepository userRepository; 

    @Override 
    public List<User> findAll() { 
    return userRepository.findAll(); 
    } 

    @Override 
    public User findById(Long userId) { 
    return userRepository.findById(userId); 
    } 
} 

:このようになります。新しい<mapper>要素を追加してsqlmap-config xmlファイルを使用してマッパーxmlファイルをリンクし、新しいリポジトリをSpringのconfigにBeanとして追加します。さらに、userMapper.xmlが大きすぎて厄介になり始めた場合、小さなファイルに分解してUserRepositoryインターフェイスを保持することができます。

+0

私はそれを調べました。それはほとんど2.6歳古いようです。それ以来、春にはたくさんのことが変わってきました。今、もっと良い方法がありますか? – ashishjmeshram

0

次のように私が扱っ:

私は.sqlファイルからクエリを保持するStringBuilderのクラスと別のBeanを追加するようjdbcTemplate豆を作成@Configurationクラスを持っています。ここに私の設定は次のとおりです。

@Configuration 
public class DBManager { 

    private static final Logger logger = LoggerFactory.getLogger(DBManager.class); 

    @Autowired 
    PropertiesUtils propertiesUtils; 

    @Bean(name = "targetJdbcTemplate") 
    public JdbcTemplate targetJdbcTemplate() throws SQLException { 
     Environment environment = propertiesUtils.getEnvironment(); 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setUrl(environment.getProperty("db.target.url")); 
     dataSource.setUsername(environment.getProperty("db.target.username")); 
     dataSource.setPassword(environment.getProperty("db.target.password")); 

     return new JdbcTemplate(dataSource); 
    } 

    @Bean(name = "targetQueryTemplate") 
    public StringBuilder targetQueryTemplate() { 
     return propertiesUtils.getSQLQueryFromFile(DBDirection.TARGET_DB); 
    } 
} 

PropertiesUtilは、次のようになります。

@Configuration 
@PropertySource(value={"classpath:app.properties"}) 
public class PropertiesUtils { 

    private static final Logger logger = LoggerFactory.getLogger(PropertiesUtils.class); 

    @Resource 
    private Environment environment; 

    public Environment getEnvironment() { 
     return environment; 
    } 

    /** 
    * to get sql query from .sql file 
    * @param dbDirection which db's query is needed 
    * @return a StringBuilder object which holds needed sql query 
    */ 
    public StringBuilder getSQLQueryFromFile(DBDirection dbDirection) { 
     String filePath = null; 
     StringBuilder sql = null; 
     BufferedReader br = null; 
     InputStreamReader input = null; 
     try { 
      if (dbDirection == DBDirection.SOURCE_DB) 
       filePath = this.environment.getProperty("db.source.query.file"); 
      else if (dbDirection == DBDirection.TARGET_DB){ 
       filePath = this.environment.getProperty("db.target.query.file"); 

      if(filePath == null || filePath.equals("")) { 
       logger.error("filePath cannot be null or empty"); 
       return sql; 
      } 

      InputStream in = PropertiesUtils.class.getClassLoader().getResourceAsStream(filePath); 
      input = new InputStreamReader(in); 
      br = new BufferedReader(input); 
      String str; 
      sql = new StringBuilder(""); 
      while ((str = br.readLine()) != null) { 
       sql.append(str); 
      } 
     } catch (IOException e) { 
      logger.error("Failed to read query from file", e); 
     } finally { 
      try { 
       if(br != null) 
        br.close(); 
       if(input != null) 
        input.close(); 
      } catch (IOException e) { 
       logger.error("Failed to close reader", e); 
      } 
     } 
     return sql; 
    } 
} 

app.properties .sqlファイルのパスを保持します。 getSQLQueryFromFileは、コンテキストの初期化中に一度ファイルを読み取ります。

次に、クエリホルダビーン(targetQueryTemplate)を自分のレポに配線します。ここに私のレポがあります:

@Repository 
public class TargetRepository implements ITargetRepository { 

    private static final Logger logger = LoggerFactory.getLogger(TargetRepository.class); 
    private static final String DEFAULT_DATE_FORMAT = "yyyyMMddHHmmss"; 

    @Autowired 
    @Qualifier("targetJdbcTemplate") 
    private JdbcTemplate targetJdbcTemplate; 

    @Autowired 
    @Qualifier("targetQueryTemplate") 
    private StringBuilder targetQueryTemplate; 

    @Override 
    public void testConnection() { 
     targetJdbcTemplate.execute("select 1 from dual"); 
    } 

    @Override 
    public int[] insert(final ArrayList<Object> list) { 
     return targetJdbcTemplate.batchUpdate(this.targetQueryTemplate.toString(), new BatchPreparedStatementSetter() { 

      @Override 
      public void setValues(PreparedStatement preparedStatement, int i) throws SQLException { 
       // batch adding 
      } 

      @Override 
      public int getBatchSize() { 
       return determineBatchSize(list); 
      } 
     }); 
    } 
} 

これは役に立ちます。

関連する問題