جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی

۱۱ مطلب با کلمه‌ی کلیدی «orm» ثبت شده است

در این بخش نگاهی میکنیم به انواع FetchMode که در org.hibernate.annotations.Fetch@ استفاده میکنیم 


در نگاه اول کاربرد استفاده از Annotation های NotNull@ و (Column(nullable = false@ یکسان بنظر می آیند و میتوان بجای یکدیگر استفاده شوند ولی اینگونه نیست.

حتی هنگام استفاده در یک JPA Entity  هر دو annotation از ذخیره مقادیر Null در دیتابیس جلوگیری میکند ولی تفاوت های چشمگیری دارند که در ادامه به آنها میپردازیم 


وقتی از Hibernate استفاده میکنیم میتوانیم از Named Parameter برای بالا بردن میزان اطمینان در ارسال اطلاعات SQL query ها استفاده کنیم اما ممکن است هنگام کار با این پارامتر ها با دو خطای متداول که یکی برای موقعی که بتنهایی از Hibernate استفاده میکنیم و دیگری hibernate پیاده سازی شده JPA بر بخوریم 


اگر یادتون باشه در بخش 2 آموزش هایبرنیت یک اشاره ای به ارث بری کردیم حالا در این بخش به بررسی کاملتر پیاده سازی ارث بری در دنیای رابطه ای می پردازیم 




توسط Criteria API میتوان یک کوئری را بصورت داینامیک و بدون استفاده از HQL ایجاد کرد

 

Criteria ctr = session.createCriteria (Cat.class);
ctr.setMaxResult(50);
List<Cat> cats = ctr.list();

کد بالا معادل select زدن روی جدولی است که در Entity کلاس Cat تعریف شده است و limit آن روی 50 است

در Criteria ما موارد خواسته شده را با متد هایش ارسال میکنیم و آن برای ما کوئری مورد نیاز را میسازد

 

 

List<Cat> cats = session.createCriteria (Cat.class)
        .add(Restrictions.like("name","Fritz%"))
        .add(Restriction.between("weight",minWeight,maxWeight))
        .list();

در کد بالا روی کلاس Cat کوئری زده که name آن با Fritz شروع شده باشد و weight آن بین دو عدد باشد

 

List cats = session.createCriteria(Cat.class)
        .add(Restriction.in("name",new String[]{"Fritz","Izi","Pk"}))
        .add(Restriction.disjunction()
                  .add(Restriction.isNull("age"))
                  .add(Restriction.eq("age",new Integer(0)))
                  .add(Restriction.eq("age",new Integer(1)))
                  .add(Restriction.eq("age",new Integer(2)))
         )
  .list();

با disjunction یک عبارت OR داخل پرانتزی ایجاد شده است و هر چه add در داخل disjunction قرار بگیرد نقش OR را خواهد داشت و برای اینکه بجای OR از AND استفاده کنیم کافی است بجای disjunction از junction استفاده کنیم 

 

میتوان بجای پاس کردن مقدار "age" از property آن استفاده کرد

Property age = Property.forName("age");

 

sql restriction : گاهی نیاز است که شروط sql را بکار ببریم 

List cats = session.createCriteria(Cat.class)
           .add(Restriction.sqlRestriction("lower({alias}.name) like lower(?)" , "Fritz%"
                      , Hibernate.STRING))
           .list();

در عبارت بالا alias همیشه به root entity alias اشاره میکند که در اینجا Cat است (در criteria باید از یک entity ساخته شود همان entity که ابتدای ساخت criteria بکار میبریم root entity است)

 

Order By در Criteria : 

List cats = session.createCriteria(Cat.class)
         .add( Restrictions.like("name","F%")
                    .addOrder(Order.asc("name").nullls(NullPrecedence.LAST))
                    .addOrder(Order.desc("age")))
          .setMaxResults(50)
      .list();

در عبارت بالا کوئری را بر اساس name صعودی و بردن null ها به انتها و age بصورت نزولی است 

 

join زدن : در criteria بصورت پیش فرض از inner join استفاده میکند

List cats = session.createCriteria(Cat.class)
         .add( Restrictions.like("name","F%"))
         .createCriteria("kittens")
         .add( Restrictions.like("name","F%"))
         .list();

در عبارت بالا kittens اشاره به جدولی دارد که با Cat رابطه ای دارد (مثلا ManyToOne) ومیتوان روی آن join زد در شرط دوم که بعد از kittens آمده است شرط روی جدول kittens اعمال میشود 

 

Alias : با متد createAlias میتوان Alias ساخت تا کوئری ها کوتاه تر شوند

 

تعریف کردن نوع join :

چون در criteria برای روابط بصورت پیش فرض از inner join استفاده میشود میتوان نوع آنرا تغییر داد

List cats = session.createCriteria(Cat.class)
         .createAlias("mate","mt",Criteria.LEFT_JOIN,Resctrictions.like("mt.name","good%"))
         .addOrder(Order.asc("mt.age"))
         .list();

 

تعریف کردن Fetch type : 

 

List cats = session.createCriteria(Cat.class)
         .add(Restrictions.in("name","Fritz%"))
         .setFetchMode("mate",FetchMode.EAGER)
         .setFetchMode("kittens",FetchMode.EAGER)
         .list();

 

Example Query : در criteria میتوان با استفاده از ابجکت Example و دادن یک نمونه از Entity ، داینامیک بیشتری به کوئری داد :

Cat cat = new Cat();
cat.setName("kittyCat");
cat.setColor(Color.Black);

List cats = session.createCriteria(Cat.class)
         .add(Example.create(cat))
         .list();

استفاده از Example با محدودیت هایی روبرو است مثلا نمیتوان روی Compose Object ها کوئری زد و یا like زدن روی رشته ها دشوار تر است 

 

**نکته : در Criteria میتوان به root entity یک alias هم داد و اگر ندهیم خودش یک alias بنام entity_ در نظر میگیرد

 

**نکته : در هایبرنیت Criteria منسوخ شده است و پیشنهاد میدهد از JPA استفاده کنیم البته Criteria در JPA پیشرفته تر و پیچیده تر است و کمی با criteria در hibernate متفاوت است ولی اصول کارشان یکسان است 

 

Projection : با projection میتوان column هایی که میخواهیم در result داشته باشیم را تعیین کنیم

List cats = session.createCriteria(Cat.class)
           .setProjection(Projections.projectionList()
                  .add(Projections.id())
                  .add(Projections.property("Entity_field_name_1"))
                  .add(Projections.property("Entity_field_name_2"))
           ).list();

در جواب لیستی از آرایه بر میگرداند که میتوان صراحتا نوع آنرا هم مشخص کرد و یک DTO ساخت :

List cats = session.createCriteria(Cat.class)
           .setProjection(Projections.projectionList()
                  .add(Projections.id())
                  .add(Projections.property("Entity_field_name_1"))
                  .add(Projections.property("Entity_field_name_2"))
           )
          .setResultTransformer(new ResultTransformer(){
                @Override
                public Object transformTuple(Object[] objects , String[] strings){
                        Cat cat = new Cat();
                         cat.setId((Integer)objects[0]);
                         cat.setName((String)objects[1]);
                         ...
                         return cat;
                }

                @Override
                public List transformList(List list){
                     return list;  
               }  )
        .list();

در متد transformList  میتوان نحوه ساخت list را هم مشخص کرد و آنرا بر گرداند

 

** نکته : میتوان از پیاده سازی های پیش فرض جهت setResultTransformer استفاده کرد که سازنده آنها در Criteria.Projection و ... قرار دارند

 

sub query با criteria : میتوان با criteria کوئری های داخلی هم ایجاد کرد که قبل از کوئری اصلی باید کوئری های داخلی با استفاده از DetachedCriteria ساخته شوند و بعد روی کوئری اصلی استفاده شوند :

 

DetachedCriteria avgWeightForName = DetachedCriteria.forClass(Cat.class,"cat2")
      .setProjection(Property.forName("weight").avg())
      .add(Property.forName("cat2.name").eqProperty("cat.name"));


List cats = session.createCriteria(Cat.class,"cat")
      .add(Property.forName("weight").gt(avgWeightForName))
      .list();