2010-07-09 15 views
10

मैं weblogic और ओरेकल का उपयोग कर एक वेब अनुप्रयोग प्रोग्रामिंग कर रहा हूँ कैसे बदलें। डेटा स्रोत को जेएनडीआई के माध्यम से कॉन्फ़िगर किया गया है, एक प्रतिबंधित डेटाबेस उपयोगकर्ता जो टेबल में डीएमएल कर सकता है, लेकिन डीडीएल नहीं कर सकता है। जैसा कि आप अनुमान लगा सकते हैं, वह उपयोगकर्ता उन तालिकाओं का स्वामी नहीं है, लेकिन उन्हें पहुंच प्रदान की गई है।जेपीए - EclipseLink - डिफ़ॉल्ट स्कीमा

मान लीजिए कि वह GUEST_USER

आवेदन जेपीए + EclipseLink उपयोग कर रहा है, और संस्थाओं को पहले से ही परिभाषित के बहुत करते हैं। मैं स्कीमा को बदलने के लिए प्रत्येक इकाई वर्ग में विशेषता लिखना नहीं चाहता हूं। मैंने इस कोड के साथ सत्र सत्रकार की कोशिश की है।

public class MyCustomizer implements SessionCustomizer{ 

    @Override 
    public void customize(Session session) throws Exception { 

    session.executeNonSelectingSQL("ALTER SESSION SET CURRENT_SCHEMA = OWNERS_SCHEMA"); 
    } 
} 

ऐसा लगता है कि वहाँ कुछ uninitiallized, मैं एक नल पॉइंटर एक्सेप्शन हो रही है कि, मैं भी यकीन है कि अगर इस तरह से इससे पहले कि वे उपयोग किया जाता है कनेक्शन के लिए स्कीमा बदलने के लिए है नहीं कर रहा हूँ। कोई नमूने या विचार?

आपकी मदद के लिए अग्रिम धन्यवाद!

उत्तर

16

आप एक xml मैपिंग फ़ाइल का उपयोग कर सकते हैं संस्थाओं के सभी एक ही स्कीमा का उपयोग से डिफाल्ट स्कीमा को परिभाषित करने के।

कुछ इस तरह काम करना चाहिए (उदाहरण के जेपीए 2.0 के लिए है, 1.0 के लिए schemaLocation बदल)

orm.xml:

<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd" 
    version="2.0"> 
    <persistence-unit-metadata> 
     <persistence-unit-defaults> 
      <schema>OWNERS_SCHEMA</schema> 
     </persistence-unit-defaults> 
    </persistence-unit-metadata> 
    . . . 
</entity-mappings> 

persistence.xml:

<persistence 
    xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
    version="2.0" > 
    <persistence-unit name="foo"> 
     . . . 
     <mapping-file>orm.xml</mapping-file> 
     . . . 
    </persistence-unit> 
</persistence> 
+0

+1 यह लग रहा है अच्छा –

+2

इस गतिशील नहीं अच्छा है लेकिन अभी भी है, क्या मैं स्कीमा दो diff db उदाहरणों के लिए एक ही एप्लिकेशन की ओर इशारा करते के दो संस्करणों के लिए बदल की जरूरत है? –

+0

इसके अलावा यदि मैं किसी विशेष इकाई प्रबंधक के लिए 'SET search_path TO ...' के साथ स्कीमा सेट करता हूं, तो अन्य तरीकों से इकाई प्रबंधक को पास करने से कोई प्रभाव नहीं पड़ता है। मुझे लगता है Wildfly (मेरे मामले में) पूल के कनेक्शन से एक पहले से वहाँ ऐसा करने का एक जेपीए मानक तरीका है सार्वजनिक डिफ़ॉल्ट स्कीमा – Chris

3

आप कर सकते हैं इसे प्रोग्रामिक रूप से करें। आप प्रत्येक सत्र के लिए डिफ़ॉल्ट स्कीमा मान कॉन्फ़िगर कर सकते हैं।

PersistenceUnitProperties.SESSION_CUSTOMIZER 

उदहारण के लिए:

public class MySessionCustomizer implements SessionCustomizer { 

    private static String schemaName; 

    public static void setSchemaName(String schemaName) { 
     MySessionCustomizer.schemaName = schemaName; 
    } 

    @Override 
    public void customize(Session session) throws Exception { 
     if (StringUtils.hasText(this.schemaName)) { 
      session.getLogin().setTableQualifier(this.schemaName); 
     } 
    } 
} 

तब इकाई प्रबंधक कारखाने गुणों के सत्र कस्टमाइज़ किया सेट

propertiesMap.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, MySessionCustomizer.class.getName()); 
+1

के साथ बनाया लेता है? –

+0

एनपीए मानक तरीका एनोटेशन ['@ टेबल'] (http://docs.oracle) में पैरामीटर स्कीमा का उपयोग कर रहा है।com/javaee/7/API/javax/हठ/Table.html) – Ati

0

मैं EJB का उपयोग सही डेटाबेस क्वेरी करने से पहले, इसलिए Interceptors का उपयोग करके मैं वर्तमान प्रमाणीकृत उपयोगकर्ता देखकर EJB संदर्भ में स्कीमा सेट करने में सक्षम हूँ।

फिर जब मैं इकाई प्रबंधक का निर्माण मैं सही स्कीमा सेट कर सकते हैं। इस तरह, तालिका नाम से पहले स्कीमा निर्दिष्ट नहीं करके, PostgreSQL search_path को किस स्कीमा को क्वेरी करने के लिए निर्धारित करेगा।

<!-- language: lang-java --> 

public class Interceptor { 

    Logger logger = Logger.getLogger(Interceptor.class); 

    /** 
    * 
    * @param ctx is always null before being passed to EJB implementation. We always query database 
    * for populating context data, making user's session accessible to all EJB implementations 
    * @return 
    * @throws Exception 
    */ 
    @SuppressWarnings({ "unchecked", "unused" }) 
    @AroundInvoke 
    public Object intercept(InvocationContext ctx) throws Exception { 
     Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 

     String ejbName = ctx.getMethod().getDeclaringClass().getSimpleName(); 
     String methodName = ctx.getMethod().getName(); 
     Boolean override_schema = false; 
     String overridden_schema = ""; 

     logger.info("Intercepting " + ejbName + "." + methodName); 

     if(auth != null) { 

      UserDetails userDetails = (UserDetails)auth.getPrincipal(); 
      String username = userDetails.getUsername(); 

      Collection<SimpleGrantedAuthority> permList = (Collection<SimpleGrantedAuthority>) auth.getAuthorities(); 
      List<String> permissions = new ArrayList<String>(); 

      for (SimpleGrantedAuthority authority : permList) { 
       permissions.add(authority.getAuthority()); 
      } 


      Query query = getMasterEntityManager() 
          .createNativeQuery(
       "SQL for retrieving the schema by the current logged in user"); 

      query.setParameter("username", username); 
      List<Object[]> result = null; //query.getResultList(); 

      if(result != null) { 
       logger.info("Interceptor: context set for " + username); 
       Object[] userObj = result.get(0); 

       getContext().getContextData().put("username", username); 
       getContext().getContextData().put("schema_name",(String)userObj[1]); 
      } 
     } 

     return ctx.proceed(); 
     } 
    } 

फिर जब आप इकाई प्रबंधक बनाते हैं, तो आप अपनी इच्छित स्कीमा सेट कर सकते हैं।

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