2012-11-02 9 views
11

मेरे पास कई वैकल्पिक फ़िल्टर बनाने के लिए कुछ जटिल प्रश्न हैं, जिसके लिए MyBatis गतिशील एसक्यूएल उत्पन्न करने के लिए आदर्श उम्मीदवार की तरह दिखता है।क्या मैं इसे निष्पादित किए बिना डायनामिक एसक्यूएल उत्पन्न करने के लिए MyBatis का उपयोग कर सकता हूं?

हालांकि, मैं अभी भी अपनी क्वेरी को उसी ढांचे में निष्पादित करना चाहता हूं जो शेष एप्लिकेशन (जो MyBatis का उपयोग नहीं कर रहा है) के रूप में।

तो मैं जो करने की उम्मीद कर रहा था वह एसक्यूएल उत्पन्न करने के लिए सख्ती से मायबेटिस का उपयोग करना था, लेकिन वहां से मेरे बाकी ऐप का उपयोग वास्तव में इसे निष्पादित करने के लिए किया गया था। क्या यह संभव है? यदि हां, तो कैसे?

उत्तर

11

हालांकि MyBatis को इसे बनाने के बाद क्वेरी निष्पादित करने के लिए डिज़ाइन किया गया था, फिर भी आप इसकी आवश्यकता के अनुसार इसके कॉन्फ़िगरेशन और "ज्ञान के अंदर" का उपयोग कर सकते हैं।

माइबेटिस एक बहुत अच्छा ढांचा है, दुर्भाग्यवश इसमें दस्तावेज़ों की तरफ कमी है, इसलिए स्रोत कोड आप मित्र हैं। यदि आप चारों ओर खुदाई करते हैं तो आपको इन कक्षाओं में टक्कर लेनी चाहिए: org.apache.ibatis.mapping.MappedStatement और org.apache.ibatis.mapping.BoundSql जो गतिशील एसक्यूएल बनाने में महत्वपूर्ण खिलाड़ी हैं।

MySQL तालिका user इस डेटा के साथ उस में:

name login 
----- ----- 
Andy a 
Barry b 
Cris c 

User वर्ग:

package pack.test; 
public class User { 
    private String name; 
    private String login; 
    // getters and setters ommited 
} 

UserService इंटरफ़ेस:

package pack.test; 
public interface UserService { 
    // using a different sort of parameter to show some dynamic SQL 
    public User getUser(int loginNumber); 
} 

UserService.xml नक्शाकार फ़ाइल यहाँ एक मूल उपयोग उदाहरण है :

<mapper namespace="pack.test.UserService"> 
    <select id="getUser" resultType="pack.test.User" parameterType="int"> 
     <!-- dynamic change of parameter from int index to login string --> 
     select * from user where login = <choose> 
              <when test="_parameter == 1">'a'</when> 
              <when test="_parameter == 2">'b'</when> 
              <otherwise>'c'</otherwise> 
             </choose> 
    </select> 
</mapper> 

sqlmap-config.file:

package pack.test; 

import java.io.Reader; 
import org.apache.ibatis.io.Resources; 
import org.apache.ibatis.mapping.BoundSql; 
import org.apache.ibatis.mapping.MappedStatement; 
import org.apache.ibatis.session.SqlSession; 
import org.apache.ibatis.session.SqlSessionFactoryBuilder; 

public class AppTester { 
    private static String CONFIGURATION_FILE = "sqlmap-config.xml"; 

    public static void main(String[] args) throws Exception { 
     Reader reader = null; 
     SqlSession session = null; 
     try { 

      reader = Resources.getResourceAsReader(CONFIGURATION_FILE); 
      session = new SqlSessionFactoryBuilder().build(reader).openSession(); 
      UserService userService = session.getMapper(UserService.class); 

      // three users retreived from index 
      for (int i = 1; i <= 3; i++) { 
       User user = userService.getUser(i); 
       System.out.println("Retreived user: " + user.getName() + " " + user.getLogin()); 

       // must mimic the internal statement key for the mapper and method you are calling 
       MappedStatement ms = session.getConfiguration().getMappedStatement(UserService.class.getName() + ".getUser"); 
       BoundSql boundSql = ms.getBoundSql(i); // parameter for the SQL statement 
       System.out.println("SQL used: " + boundSql.getSql()); 
       System.out.println(); 
      } 

     } finally { 
      if (reader != null) { 
       reader.close(); 
      } 
      if (session != null) { 
       session.close(); 
      } 
     } 
    } 
} 

और परिणाम:

Retreived user: Andy a 
SQL used: select * from user where login = 'a' 

Retreived user: Barry b 
SQL used: select * from user where login = 'b' 

Retreived user: Cris c 
SQL used: select * from user where login = 'c' 
+0

हो सकता है, यह वास्तविक मूल्य के बजाय पता चलता '?'। जैसे 'जहां लॉगिन =?'। इस पर चारों ओर कोई काम? धन्यवाद (मैं मैपर वर्ग का उपयोग नहीं कर रहा हूं) – agpt

0

बस Bogdan के सही जवाब में जोड़ने के लिए:

<configuration> 
    <settings> 
     <setting name="lazyLoadingEnabled" value="false" /> 
    </settings> 
    <environments default="development"> 
     <environment id="development"> 
      <transactionManager type="JDBC"/> 
      <dataSource type="POOLED"> 
       <property name="driver" value="com.mysql.jdbc.Driver"/> 
       <property name="url" value="jdbc:mysql://localhost/test"/> 
       <property name="username" value="..."/> 
       <property name="password" value="..."/> 
      </dataSource> 
     </environment> 
     </environments> 
    <mappers> 
     <mapper resource="pack/test/UserService.xml"/> 
    </mappers> 
</configuration> 

AppTester परिणाम दिखाने के लिए आप की जरूरत है पास करने के लिए आपके इंटरफ़ेस पैरामीटर के लिए गेटटर के साथ JavaBean getBoundSql(), यदि आपके इंटरफ़ेस में अधिक जटिल हस्ताक्षर हैं।

मान लीजिए कि आप लॉगिन नंबर और/या उपयोगकर्ता नाम के आधार पर उपयोगकर्ता से पूछना चाहते हैं। आपका इंटरफेस इस प्रकार दिखाई देंगे:

package pack.test; 
public interface UserService { 
    // using a different sort of parameter to show some dynamic SQL 
    public User getUser(@Param("number") int loginNumber, @Param("name") String name); 
} 

मैं मैपर कोड बाहर जा रहा हूँ, क्योंकि यह इस चर्चा के लिए अप्रासंगिक है, लेकिन AppTester में अपने कोड हो जाना चाहिए:

[...] 
final String name = "Andy"; 
User user = userService.getUser(i, name); 
System.out.println("Retreived user: " + user.getName() + " " + user.getLogin()); 

// must mimic the internal statement key for the mapper and method you are calling 
MappedStatement ms = session.getConfiguration().getMappedStatement(UserService.class.getName() + ".getUser"); 
BoundSql boundSql = ms.getBoundSql(new Object() { 
    // provide getters matching the @Param's in the interface declaration 
    public Object getNumber() { 
    return i; 
    } 
    public Object getName() { 
    return name; 
    } 

}); 
System.out.println("SQL used: " + boundSql.getSql()); 
System.out.println(); 
[...] 
1

हर कोई BoundSql उपयोग करने के लिए कैसे जानता है ।getSql() MyBatis से एक paramaterized क्वेरी स्ट्रिंग प्राप्त करने के लिए, इस तरह:

// get parameterized query 
MappedStatement ms = configuration.getMappedStatement("MyMappedStatementId"); 
BoundSql boundSql = ms.getBoundSql(parameters); 
System.out.println("SQL" + boundSql.getSql()); 
// SELECT species FROM animal WHERE name IN (?, ?) or id = ? 

लेकिन अब आप समीकरण के दूसरी छमाही कि प्रश्न चिह्न के अनुरूप मानों की सूची की जरूरत है,:

// get parameters 
List<ParameterMapping> boundParams = boundSql.getParameterMappings(); 
String paramString = ""; 
for(ParameterMapping param : boundParams) { 
    paramString += boundSql.getAdditionalParameter(param.getProperty()) + ";"; 
} 
System.out.println("params:" + paramString); 
// "Spot;Fluffy;42;" 

अब आप इसे चलाने के लिए कहीं और भेजने के लिए क्रमबद्ध कर सकते हैं, या आप इसे लॉग में प्रिंट कर सकते हैं ताकि आप उन्हें एक साथ सिलाई कर सकें और मैन्युअल रूप से क्वेरी चला सकें।

* परीक्षण नहीं कोड, नाबालिग प्रकार मुद्दों या की तरह

मेरे लिए
संबंधित मुद्दे

 संबंधित मुद्दे