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

java programming language

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

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

۱۰۷ مطلب با موضوع «java» ثبت شده است

به لیست annotaion هایی که در پکیج org.springframework.beans.factory.annotation  و org.springframework.context.annotation قرار دارند Spring Core Annotaion میگویند که عمدتا برای استفاده در Dependency Injection کاربرد دارند و قدرت مانور بالایی در Develop Time به ما می دهند که در ادامه به انها می پردازیم :


maven : یکی از پر کاربردترین ابزار های جاوا برای package بندی , build , deploy , compile , test , document generation پروژه ها است که باعث میشود همه توسعه دهنده ها با استفاده از maven از یک استاندارد پیروی کنند و از اعمال سلیقه هر توسعه دهنده تا حد زیادی جلوگیری میشود و توسعه دهنده بعدی میتواند با ساختار پروژه راحت ارتباط بر قرار میکند

 

plugin ها :  در maven تعداد بسیار زیادی plugin برای کارهای مختلف وجود دارد ما نیز میتوانیم پلاگین مورد نیاز خودمان را هم بنویسیم

 

Archetype : به مشخصه پروژه میپردازد و کمک میکند ساختار پروژه را ایجاد بکنیم  و شامل حداقل سه جزییات groupid , artifactid , version  است

- groupid همان packaging ما است که مشخص میکنیم 

- artifactid اسم پروژه است که در انتهای packaging ما قرار میگیرد

- version هم طبق semantic versioning شماره ورژن جاری را مشخص میکنیم

 

repository : در maven بصورت محلی یک repository روی دیسک ایجاد میکند و در دفعات بعد که یک کتابخانه را بخواهیم استفاده کنیم دوباره آنرا دانلود نمیکند

 

بعد از دانلود و خارج کردن از حالت فشرده میبایست مسیر آنرا بصورت local variable به سیستم معرفی کنیم

 

export MVN_HOME=/opt/maven
export PATH=$MVN_HOME/bin:$PATH

 

config : برای ست کردن config مورد نظر باید در آدرس MVN_HOME/conf/setting.xml فایل xml را ویرایش کنیم 

 

pom.xml : در این فایل کلیه تنظیمات و مشخصات و dependency های پروژه در آن وجود دارد که بعد از ایجاد پروژه با maven در اختیار ما خواهد بود و اگر بخواهیم تغییری را اعمال کنیم از طریق این فایل میتوانیم 

 

در تگ dependencies میتوانیم کتابخانه های مورد نیاز و وابستگی ها را اضافه کنیم که هر وابستگی در تگ dependency قرار میگیرد و شامل حداقل تگ های داخلی groupid , artifactid , version , scope است با scope مشخص میکنیم که این کتابخانه در چه مرحله ای از پروژه قرار است مورد استفاده قرار گیرد که شامل موارد زیر است : 

 

- test : فقط در جریان توسعه نرم افزار که همراه با تست است آن کتابخانه را استفاده میکند مثل junit

- providen : یعنی در آینده این کتابخانه توسط ما یا عامل دیگری برای پروژه قراهم خواهد شد و طی فرایند کامپایل و ساخت jar فایل انرا اضافه نمیکند مثل کتابخانه servlet که در servlet container ها موجود است

- compile : بصورت پیش فرض روی این گزینه ست شده است و یعنی این کتابخانه را هنگامی که پروژه کامپایل و ساخته میشود استفاده کند

- runtime : مشابه provided است 

- system : که اشاره میکند این کتابخانه در سیستم موجود است و باید به مسیر کتابخانه های پروژه آنرا اضافه کند

 

دستورات maven : 

 

قبل از پرداختن به دستورات maven در محیط ترمینال اطمینان حاصل کنید که شاخه جاری ای که در آن قرار گرفته اید شاخه اصلی پروژه است و فایل pom.xml موجود است چون maven تنها میتواند از روی این فایل کار کند و دستورات را روی پروژه اعمال کند

 

mvn clean : شاخه target و فایل های داخلش را که مربوط به build گرفتن پروژه بوده را پاک میکند و پروژه را اماده build میکند

mvn package : این دستور پروژه را compile میکند و آنرا build میکند و شاخه target را هم میسازد

mvn clean install : این دستور علاوه بر compile کردن آنرا در لیست مخزن محلی قرار میدهد

test skip کردن : در طی فرآیند compile و build تست هم انجام میشود که لاگ آنرا در کنسول میتوان دید برای انجام نشدن تست میبایست سویچ مورد نظر را اعلام کرد : mvn clean install -DskipTests=true

 

 

 

 

 

 

 

 

 

 

 

 

 

 

اگر یادتون باشه در بخش 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();

 

 

 

 

 

 

 

 

 

 

HQL :

زبانی شبیه SQL برای کوئری زدن در هایبرنیت که به جای بکار گرفتن نام جداول و ستون‌ها با entity ها و فیلد ها کار میکند

نمونه : from Cat as cat  برای select زدن روی جدولی که در کلاس Cat تعریف شده است

 

میتوانیم از دو جدول هم کوئری بگیریم که جواب آن بصورت ضرب دکارتی بر میگردد  

from Formula , Parameter

و خروجی را بصورت ArrayList ای از آرایه ها خواهیم داشت و اندیس اول از Formula و اندیس دوم از Parameter خواهد بود و اگر بخواهیم لیست برگشتی فقط لیستی از Formula باشد میتوان HQL را به این صورت نوشت :

select f from Formula f , Parameter 

و اگر بخواهیم بجای List ای از آرایه ها List ای از List ها بگیریم میتوان HQL را به این صورت تغییر داد :

select new List(f) from Formula f , Parameter 

 

از همین روش بالا میتوان ابجکت های model ای داشت که در constractor آرگومان هایی را دریافت کند و در HQL صراحتا مقادیر دریافتی را به آن ارگومان ها پاس بدهیم و خروجی List ای از آن ابجکت دریافت کنیم

**نکته : اصولی نیست که کوئری را برای دو Entity بزنیم و باید تا آنجا که ممکن است دوری کنیم

 

fetch : در کوئری های join زدن ها اگر بخواهیم ستون های جدول دوم را هم دریافت کنیم میتوانیم بعد از کلمه join از fetch استفاده کنیم 

 

**نکته : left join پرفرمانس دیتابیس را تا حد زیادی کم میکنم و راه حل این است که بجای اینکه مقادیر f.key را optional بگیریم حتما برای مقادیر optional از یک مقدار پیش فرض که توسط خودمان تعیین میشود استفاده کنیم که همیشه بتوانیم از inner join استفاده کنیم

 

Named Query :

میتوان در کلاس های Entity کوئری های از پیش تعریف شده ای با یک نام ایجاد کرد و در طول برنامه با استفاده از نام کوئری از آن استفاده کرد

@Entity
@NamedQueries(
     @NamedQuery(name="getUserById" , query="from User where userId = :pUserId")
)
public class User {

private int userId;
private String username;
...
}

با استفاده از Name Query ها کوئری ها از لحاظ ساختاری و اجر چک میشوند و آنها در حافظه cache می شوند

 

Query query = session.createNamedQuery("getUserById")
                    .setParameter("pUserId",1);

List<User> list = query.list();

 

Native Query :

هایبرنیت از کلیه دستورات و امکانات SQL استفاده نمیکند مثل Union و یا میخواهیم بجای HQL از SQL استفاده کنیم ، ما میتوانیم با استفاده از Native Query از آنها استفاده کنیم

 

session.createNativeQuery ("select * from user" , User.class).list();

 

که همانند NamedQueries@ میتوان از NativeQueries@ استفاده کرد و دسته ای از Native Query ها را ایجاد کرد