Child pages
  • Hibernate dynamikus tabla prefixxel
Skip to end of metadata
Go to start of metadata

Sziasztok!

Alap szinten mar foglalkoztam hibernate-vel de most sajat projectben akadtam el :) keszitek egy ugyviteli rendszert(cliens -> GWT, server -> java) es a rendszer 
ahol minden ugyfel ugyan ott lep be viszont az o kis rendszere egy adatbazisban van csak prefixxel van ellatva... na most meg tudom valahogy oldani hibernattel hogyha belep XYZ akkor o az entity-knel tudja hogy az XYZ_ugyfelek tablabol vegyek az ugyfelek model-t?

@Entity
@Table(name="???_ugyfel")
public class Ugyfel{......}

??? lenne a prefix de ez ugye mindig attol valtozik hogy az adott belepett user melyik rendszeren dolgozik...

ez igy ertheto ? :)

elore is koszonom a helpet :P

      
      
Page viewed times
#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))
  • No labels

13 Comments

  1. Érteni értem, de ez eléggé antipattern dolognak néz ki JPA szempontból... (smile)

    A megoldás az lehet, hogy külön sémába szervezed a táblákat és az adott felhasználóval az adott sémához csatlakozol, de ekkor magad kell kezelned az összes olyan dolgot, amit a konténer egyébként elvégez.

    1. antipattern ? (smile) miert akkor jobb lenne kulon db-be userenkent ? 

      megmondom az igazat hogy a schemas dolgokkal nem nagyon foglalkoztam meg...(inkabb mas megoldas fele tendalodok....(smile))

      lehet hogy most hulyeseget mondok de ezt neztem(csak ki kell probalnom hogy mikor hivodik meg a tableName metodus) http://stackoverflow.com/questions/8573468/hibernate-data-object-with-a-dynamic-table-name-by-annotations + igazabol nem tudom hogy a hibernate alap szinten hogy is mukodik tehat session-kent dolgozik az objektumokkal vagy apponkent ... mert ha session-kent akkor http://hibernateannotation.blogspot.hu/2012/03/hibernate-singleton-sessionfactory.html valami ilyesmivel + a stackoverflow-s linkkel kombinalva lehet meg lehetne oldani(mondjuk amikor belep a user akkor a session-ben eltarolom hogy mi a db prefix-e), de ha meg a hibernate onnantol fut folyamatosan hogy a tomcattel elinditom az appot akkor tenyleg nem tudom mi a megoldas ... (+ kesobbiekben lehet lesz olyan is hogy tobb felhasznalo fog ugyan ahoz a prefix-es tablakhoz es akkor is jo lenne ha a hibernate ezt tudna kezelni nehogy zavar legyen (tongue) )

       

      thx a helpet

      1. Antipattern azt jelenti, hogy "szívni fogsz vele", mert nincs nagyon eszköz, ami azt a módszert támogatná, ha találsz megoldást, az se biztos, hogy örök életig benne marad az adott framework-ben, mert nem illeszkedik a többi eszközhöz.

        A Hibernate tud ilyet, de ezzel kiesel a JPA keretei közül, kiesel a keretrendszerek támogatásai közül, és magadnak kell megoldani mindent, gyakorlatilag azzal foglalkozol többet, hogy kialakíts egy környezetet, ahol aztán a tényleges munkát el tudod végezni.

        Miért kell külön táblába tenni a különböző dolgokat, ahelyett, hogy egy relációs adatbázis keretei között oldanád meg a dolgot egy darab "prefix" táblával és minden egyéb táblába beletennél egy ilyen "prefix" mezőt. Ezt nagyon szépen támogatja a JPA is, és rögtön csak azzal kellene foglalkoznod, ami a feladat, nem pedig a keretek faragásával. (smile)

        1. adatbazis szervezes teren meg nincs nagy tapasztalatom (sad) mit 

          "Miért kell külön táblába tenni a különböző dolgokat, ahelyett, hogy egy relációs adatbázis keretei között oldanád meg a dolgot egy darab "prefix" táblával és minden egyéb táblába beletennél egy ilyen "prefix" mezőt. Ezt nagyon szépen támogatja a JPA is, és rögtön csak azzal kellene foglalkoznod, ami a feladat, nem pedig a keretek faragásával."

          kerlek ezt fejstd ki bovebben (smile)

          mert pont azert akartam hibernatet hogy a db dolgokkal ne kelljen annyit foglalkozni (smile) azert talaltam ki a tabla prefixes dolgokat mert igy akkor vegulis az egesz rendszerben egy db lenne(jobb megoldas ha rendszerenkent inkabb kulon db lenne ? akkor megszunik a prefix... csak nem tudom hibernate orulne-e neki ...) viszont nem akarok tobb ugyfel adatait egy tablaban tarolni...(bar lehet a vegen csak ez a megoldas marad ? ;( ) (bar ma haza erek akkor a dynamic table-s linket kiprobalom...) bar pont azt akarom elkerulni amit irtal hogy a vegen nekem kelljen mindent megoldani (smile)

           

          tenyleg koszonok minden segitseget es johet linkek is mert meg szeretnem tanulni ezen dolgokat is (tongue)

          1. Ha nem akarod több ügyfél adatait egy táblában tárolni, akkor ne tárold. Egy ügyfél adatait miért akarod egy táblában tárolni? Miért pont az ügyfél a határ vágni akarod? (smile)

            1. Bocsanat lehet rosszul magyaraztam (smile) 

              Tehat van egy users tabla(ami kozos) ennek a belepsnel van jelentosege ... amennyibe belepett akkor kiderul hogy mi a prefix-e ... ezek utan pl prefix_ugyfelek tablabol szedi az o ugyviteli rendszerehez az ugyfeleket... tehat prefix_ugyfelek tablaban az o rendszerehez tartozo ugyfelek vannak .... azert van igy mert barmikor le tudok konyen valasztani egy ugyfelet(rendszert hasznalo ugyfelet) ha kell vagy torolni ....

              egyszerubb ha ezentul a user es customer szavakat hasznalom ? (smile)

              igazabol addig mar eljutottam hogy a namestrategy-val mukodokepes a dolog csak kozben meg ugy veltem hogy minek minden keresnel ujra a new Configuration().configure().setNamingStrategy(new MyNamingStrategy()).buildSessionFactory(); sort hivni ezert valami filter-t probalok nezni de azzal meg az a gond hogy hamarabb lefut mint a java session letrejonne (sad) ugyhogy vagy a filterben oldom meg vagy a RequestFactoryServlet-bol szarmaztatok es abban meg nem tudom ...

               

              csak azt nem tudom hogy akkor mi lesz ha belep 2 olyan user akinek ugyan az a prefixxe, akkor a hibernate mit fog szolni amikor pl nyomok egy updatet vagy valami hasonlot (bar majd megnezem hogy van a tabla lockolas...)

               

              elore is bocsika ha neha nem a jo szakkifejezeseket hasznalom de en magamtol alltam neki tanulni javat 1 eve (smile)  es hat sajna vannak tudas hianyosagi alapok (sad)

              1. Mi akadályoz meg abban, hogy egy userId-t beletegyél az ugyfelek táblába? És akkor nem kell hozzá semmi varázslat. Törölni egyszerű, ha egy táblában kezeled. A leválasztás az most igény? Biztos, hogy le kell majd választani? Miért akarod fragmentálni a rendszert?

                Ha egy régi legacy rendszer adatbázisára szeretnél ráépíteni egy újabb felületet, akkor egy szavam nem lenne, de egy kvázi zöldmezős fejlesztésnél ez őrültség. Ha jobban megérted a Java keretrendszerek működését, akkor másfél-két év múlva a falba fogod verni a fejed, hogy miért nem hallgattál rám... (smile)

                1. Mar most a falba verem a fejemet (tongue) mert teljesen igazad van de az ugyfel kerte hogy userenkent kulon db vagy prefix legyen .... (sad) egyebkent en is azt csinalnam amit irtal ... de sajnos ezt most igy kell megoldanom ... ;(

                  igy sajnos sok mindennel szop** fogok meg ....

                  szerinted az nagy butasag ha session nyitasnal a hibernate SessionFactory-t elteszem a session-be ? vagy a sessionFactory.openSession(Session)-t teszem el http sessionbe es irok egy http session listener-t a destroy-ra es csak akkor zarom le ? (mert ha jol tudom akkor eleg a hibernate-nel ha mindig commitolok ?(smile) ezeket azert kerdezem mert a cliens oldalnal elofordulhat hogy akar par percen belul tobb keres is befut es hat teljesitmeny miatt nem biztos hogy jo ha mindig ujra beolvasom a configot stb ....

                  1. Értem én, hogy a megrendelő diktál, de mindenben nem kellene igazat adni neki... (smile)

                    Beleteheted a HttpSession-be, de nem lesz replikálható, se perzisztálható, így a HA működést elfelejtheted (de gondolom Tomcat miatt nem is cél), illetve talán a konténer adta tranzakciókezelést is elfelejtheted, neked kell gondoskodnod a tranzakciók lezárásáról és kezeléséről. Szóval szerintem Java EE szempontból csak hátránya van ennek a megoldásnak.

                  2. En elobb megprobalnam meggyozni az ugyfelet, hogy amig te vagy a fejleszto, addig ne o akarja megmondani, hogy hogyan alakitsd ki az adatbazist. 

                    Az levalasztas egyebkent meg egy darab ugyfelek tabla eseten is egyszeru, hiszen a sema adott (indexestol), az adott userid-hez tartozo ugyfeleket fogod es egy INSERT INTO ujdb.ugyfelek SELECT * FROM regidb.ugyfelek WHERE id = <USERID> szeru sql scripttel mar le is valasztottad. Utana meg majd lehet takaritani.

                2. + azt elfelejtettem mondani hogy azert is van ez a prefixes megoldas mert lesz egy alap rendszer amit mondjuk xy user megvesz hasznalatra ... ez meg nalunk fut de ahogy ker extra funkciokat ugy mar kulon projectkent fogjuk kezelni es gondolj bele ha mar jo sok adat van a tablakban es azok soroan kapcsolodnak akkor milyen jo munka kiolvasni es az indexeket ujra rendezve uj db-t letrehozni ...

                  1. Próbáld meg elkerülni a kód és a futtató környezet fragmentációját, mert azzal később folyamatosan fejlesztési, tesztelési és üzemeltetési problémáid lesznek. Az adatbázis rendszerek azért vannak, hogy az adatok közötti relációkat kezeljék, nyugodtan alapozz arra, hogy ez menni fog egy viszonylag gyengébb gépen is több millió soros adatmennyiségig, ha jól választod meg az indexeket, akkor bőven kezelhetők a több tucat millió soros adatok is, ha ennél több kell, akkor lehet logikailag vagy fizikailag partícionálni az adatbázist. Szóval normál eszközökből van bőven, feleslegesen ne szívasd magad... (smile)

  2. Kozben orvosoltam a problemat ... lehet nem a legjobb megoldas lett (ha valaki tud jobbat vagy ezen javitana az kerem jelezze(smile) ) gondoltam megosztom, mert egyebkent sok hasonlo kerdest talalni a neten csak teljes megoldas nincs ...

    megoldasrol roviden:

    kell annotation amivel jelzem hogy az adott entity-nel kell-e prefix...

    a hibernate.cfg.xml bol olvasom ki a mappingolt class-okat es ugy vizsgalom meg....

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface TablePrefix {
    boolean withPrefix() default true;

    }

    --------------------------

    import java.io.IOException;

    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;

    import javax.persistence.Table;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSession;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;

    import org.apache.log4j.Logger;
    import org.hibernate.cfg.DefaultNamingStrategy;
    import org.w3c.dom.DOMException;
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;

    public class PrefixNamingStrategy extends DefaultNamingStrategy {
    private static final long serialVersionUID = 5140093915985482861L;
    private static Logger logger = Logger.getLogger(PrefixNamingStrategy.class);
    private static List<String> prefixed = new ArrayList<String>();
    private static boolean initPrefixedTables = false;

    @Override
    public String tableName(String tableName) {
    getPrefixedTables();
    if (prefixed.contains(tableName)) {
    HttpSession session = SessionHelper.getSession();
    String attribute = (String) session.getAttribute("db_prefix");
    logger.trace("create " + attribute + "_" + tableName + " table namingstrategy");
    return attribute + "_" + tableName;
    }
    return tableName;
    }

    private void getPrefixedTables() {
    if (initPrefixedTables == false) {
    // final long startTime = System.nanoTime();
    // final long endTime;
    try {
    HttpSession session = SessionHelper.getSession();
    ServletContext servletContext = session.getServletContext();
    InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/"
    + (SessionHelper.getServletPath().toLowerCase() + "-hibernate.cfg.xml").replace("/", ""));
    DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = newInstance.newDocumentBuilder();
    Document doc = builder.parse(resourceAsStream);
    doc.getDocumentElement().normalize();
    NodeList elementsByTagName = doc.getElementsByTagName("mapping");
    for (int i = 0; i < elementsByTagName.getLength(); i++) {
    Node item = elementsByTagName.item(i);
    Class<?> classz = Class.forName(item.getAttributes().getNamedItem("class").getNodeValue());
    TablePrefix annotation = classz.getAnnotation(TablePrefix.class);
    if (annotation != null && annotation.withPrefix()) {
    Table annotation2 = classz.getAnnotation(Table.class);
    if (annotation2.name().equals("")) {
    logger.warn("Hibernate entity-nek nincs @Table megadva!!! (" + classz + ")");
    } else {
    prefixed.add(annotation2.name());
    }
    }
    }

    initPrefixedTables = true;

    } catch (ParserConfigurationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (SAXException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (DOMException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // finally {
    // endTime = System.nanoTime();
    // }
    // final long duration = endTime - startTime;
    }
    }
    }

     

    a hibakezeles meg nincs igazan megvalositva (smile) + SessionHelper.getServletPath().toLowerCase() -ra nalam azert van szukseg mert 2 GWT-s modul van (1 login, 2 meg maga az app, bar mar hibernate.cfg.xml egyesitesre is talaltam megoldast csak nem implementaltam ...) mivel ez tenyleg egy egyszeru cucc ezert nem irnam le a mukodeset nagyon (tongue) elesiteni igy kell

    new Configuration().setNamingStrategy(new PrefixNamingStrategy())
    .configure((SessionHelper.getServletPath().toLowerCase() + "-hibernate.cfg.xml").replace("/", ""))
    .buildSessionFactory();

    koszonom mindenkinek a tanacsokat es a helpet! mivel ilyen segitokeszek vagytok ezert meg lesz par kerdesem (smile)