در این روش به ازای کلاس پدر و زیرکلاس ها هر کدام یک جدول ساخته می شود و زیرکلاس ها توسط یک کلید به کلاس پدر وصل می شوند.بنابراین فیلدهای کلاس پدر در زیرکلاسها تکرار نمی شوند.
فرض کنیم کلاسهای زیر را داریم:
public class Employee {
private int employeeId;
private String name;
//getters and setters
}
public class RegularEmployee extends Employee{
private float salary;
private int bonus;
//getters and setters
}
public class ContractEmployee extends Employee{
private float pay_per_hour;
private String contract_duration;
//getters and setters
}
در فایل xml قرار می دهیم:
<hibernate-mapping >
<class name="Employee">
<id name="employeeId" >
<generator class="increment" />
</id>
<property name="name" />
<joined-subclass name="RegularEmployee" extends="Employee">
<key column="employeeId" />
<property name="salary" />
<property name="bonus"/>
</joined-subclass>
<joined-subclass name="ContractEmployee" extends="Employee">
<key column="employeeId" />
<property name="pay_per_hour" />
<property name="contract_duration" />
</joined-subclass>
</class>
</hibernate-mapping>
- فرشته حقیقی 5 سال قبل پاسخ داد
- آخرین فعالیت در 5 سال قبل
در این استراژی به ازای هر کلاس یک جدول ایجاد می شود و جداول زیرکلاسها شامل ستونهای سوپرکلاس نیز خواهند بود.
public class Employee {
private int id;
private String name;
//getters and setters
}
public class RegularEmployee extends Employee{
private float salary;
private int bonus;
//getters and setters
}
public class ContractEmployee extends Employee{
private float pay_per_hour;
private String contract_duration;
//getters and setters
}
برای پیاده سازی این روش در فایل xml با استفاده از تگ <union-subclass> زیرکلاسها را مشخص می کنیم.
<hibernate-mapping>
<class name="Employee" >
<id name="id">
<generator class="increment"></generator>
</id>
<property name="name"></property>
<union-subclass name="RegularEmployee" >
<property name="salary"></property>
<property name="bonus"></property>
</union-subclass>
<union-subclass name="ContractEmployee" ">
<property name="pay_per_hour"></property>
<property name="contract_duration"></property>
</union-subclass>
</class>
</hibernate-mapping>
- فرشته حقیقی 5 سال قبل پاسخ داد
در این روش برای همه ی زیرکلاسها و همچنین کلاس پدر فقط یک جدول ایجاد می شود.در این جدول یک ستون به نام discriminator column برای تشخیص اینکه هر رکورد به کدام کلاس تعلق دارد توسط هایبرنت ایجاد می شود.
فرض کنیم کلاسهای زیر را داریم:
public class Employee {
private int id;
private String name;
//getters and setters
}
public class RegularEmployee extends Employee{
private float salary;
private int bonus;
//getters and setters
}
public class ContractEmployee extends Employee{
private float pay_per_hour;
private String contract_duration;
//getters and setters
}
روش single class با استفاده از xml بصورت زیر می شود:
<hibernate-mapping>
<class name="Employee" table="EMPLOYEES" discriminator-value="emp">
<id name="id">
<generator class="increment"></generator>
</id>
<discriminator column="type" type="string"></discriminator>
<property name="name"></property>
<subclass name="RegularEmployee" discriminator-value="reg_emp">
<property name="salary"></property>
<property name="bonus"></property>
</subclass>
<subclass name="ContractEmployee" discriminator-value="con_emp">
<property name="pay_per_hour"></property>
<property name="contract_duration"></property>
</subclass>
</class>
</hibernate-mapping>
- فرشته حقیقی 5 سال قبل پاسخ داد
فرض کلاس زیر را داریم که در آن یک لیست از آبجکتهای کلاس دیگری نگه داری می شود.برای پیاده سازی این کالکشن باید از تگهای <one-to-many>یا<many-to-many> استفاده کنیم:
public class Question {
private int id;
private String qname;
private List<Answer> answers;
//getters and setters
}
public class Answer {
private int id;
private String answer;
private String posterName;
//getters and setters
}
پیاده سازی هایبرنت بصورت زیر انجام می شود:
<class name="Question" table="Question">
<id name="id">
<generator class="increment"></generator>
</id>
<property name="qname"></property>
<list name="answers" >
<key column="qid"></key>
<index column="type"></index>
<one-to-many class="Answer" />
</list>
</class>
عبارت <index column="type"></index> برای کالکشنهای list و map میبایست قید گردد چون این کالکشن ها ایندکس شده هستند.
- فرشته حقیقی 6 سال قبل پاسخ داد
در هایبرنت برای هر کالکشن یک جدول ساخته می شود.فرض کنیم کلاس زیر را داریم که یک کالکشن set در آن داریم:
public class Employee {
private int employeeId;
private String employeeName;
private Set<String> phoneNumbers;
//getter and setter
}
در فایل Employee.xml داریم:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<id name="employeeId">
<generator class="increment"></generator>
</id>
<property name="employeeName"></property>
<set name="phoneNumbers" table="PHONE">
<key column="phoneid"></key>
<element column="phone_number" type="string"></element>
</set>
</class>
</hibernate-mapping>
در اینجا phoneid کلید خارجی می باشد و به کلید جدول کلاس ارجاع می دهد که در اینجا به employeeId ارجاع دارد.
- فرشته حقیقی 6 سال قبل پاسخ داد
در این روش به ازای کلاس پدر و زیرکلاس ها هر کدام یک جدول ساخته می شود و زیرکلاس ها توسط یک کلید به کلاس پدر وصل می شوند.بنابراین فیلدهای کلاس پدر در زیرکلاسها تکرار نمی شوند.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
@Column(name="employee_id")
private Long id;
private String employeeId;
private String firstName;
private String lastName;
private String email;
}
@Entity(name = "joinedTableContractEmployee")
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "employee_id")
public class ContractEmployee extends Employee {
private LocalDate contractStartDate;
private LocalDate contractEndDate;
private String agencyName;
}
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
این استراژی مانند روش mapped superclass است که به ازای هر زیرکلاس یک جدول ایجاد می شود با این تفاوت که در این استراتژی برای کلاس پدر نیز یک جدول ایجاد می شود.بنابراین در این روش می توانیم ارتباط بین سوپرکلاس و زیرکلاس را پیدا کنیم.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Employee {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private Long id;
private String employeeId;
private String firstName;
private String lastName;
private String email;
}
@Entity
public class ContractEmployee extends Employee {
private LocalDate contractStartDate;
private LocalDate contractEndDate;
private String agencyName;
}
- فرشته حقیقی 6 سال قبل پاسخ داد
در این روش برای همه ی زیرکلاسها و همچنین کلاس پدر فقط یک جدول ایجاد می شود.مزیت این روش این است که کوئری ها ساده و بهینه خواهند بود اما عیب آن این است که مقادیر بعضی ستونها null خواهد بود.انوتیشن این روش بسیار ساده می باشد که عبارتند از Inheritance(strategy=InheritanceType.SINGLE_TABLE@ و برای اینکه مشخص کنیم که هر رکورد متعلق به چه entity است از انوتیشن های DiscriminatorColumn @DiscriminatorValue@ استفاده می کنیم
فرض کنیم یک کلاس کارمند و دو زیرکلاس کارمندقراردادی و کارمند رسمی داریم.کلاس کارمند که کلاس پدر می باشد بصورت زیر تعریف می شود:
@Entity
@Table(name = "EMPLOYEE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value="employee")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
//setters and getters
}
زیرکلاسها نیز بصورت زیر تعریف می شوند:
Entity
@DiscriminatorValue("regularemployee")
public class Regular_Employee extends Employee{
@Column(name="salary")
private float salary;
@Column(name="bonus")
private int bonus;
//setters and getters
}
@Entity
@DiscriminatorValue("contractemployee")
public class Contract_Employee extends Employee{
@Column(name="pay_per_hour")
private float pay_per_hour;
@Column(name="contract_duration")
private String contract_duration;
//setters and getters
}
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
در این روش یک کلاس پدر و تعدادی زیرکلاس داریم اما کلاس پدر entity نخواهد بود یعنی به ازای کلاس پدر جدولی در دیتابیس نخواهیم داشت.این روش برای به اشتراک گذاشتن فیلدها مناسب است و از تعریف مجدد فیلدهای تکراری جلوگیری می شود. برای انجام کوئری روی جداول نیازی به join جداول نداریم و از این نظر این یک مزیت می باشد چون نیازی به کوئری های پیچیده نمی باشد.
نقطه ضعف این روش این است که ارتباطی بین جداول وجود ندارد و همچنین نمی توانیم با کوئری تمام زیرکلاسهای پدر را استخراج کنیم.
برای مشخص کردن کلاس پدر از انوتیشن MappedSuperclass@ استفاده می کنیم.
@MappedSuperclass
public class Person {
@Id
@Column
private long personId;
@Column
private String name;
// constructor, getters, setters
}
در نظر داشته باشید برای کلاس پدر انوتیشن Entity@ بکار نمی بریم.
برای تعریف یک زیرکلاس به صورت زیر عمل می کنیم:
@Entity
public class MyEmployee extends Person {
@Column
private String company;
// constructor, getters, setters
}
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
فرض کنیم دو کلاس person و Address داریم که رابطه یک به چند (one to many) دارند. یعنی هر شخص می تواند چند آدرس داشته باشد. جداول این دو کلاس در مثالهای قبل بیان شده اند. انوتیشن این کلاسها به صورت زیر می باشد:
@Entity
@Table(name="PERSON" uniqueConstraints = {
@UniqueConstraint(columnNames = "ID"),
})
public class Person {
private Integer id = null;
/** * Gets id (primary key). */
@Id
@GeneratedValue(strategy=GenerationType. IDENTITY)
@Column(name="ID ")
@Column(name="FIRST_NAME" unique = true, nullable = false)
private String firstName;
@Column(name="LAST_NAME")
private String lastName;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="PERSON_ID", nullable=false)
private Set<Address> addresses;
public Integer getId()
{ return id; }
public void setId(Integer id)
{ this.id = id; }
public String getFirstName()
{ return firstName; }
public void setFirstName(String firstName)
{ this.firstName = firstName; }
public String getLastName()
{ return lastName; }
public void setLastName(String lastName)
{ this.lastName = lastName; }
public Set<Address> getAddresses()
{ return addresses; }
public void setAddresses(Set<Address> addresses)
{ this.addresses = addresses; }
}
@Entity
@Table(name="ADDRESS" uniqueConstraints = { @UniqueConstraint(columnNames = "ID"), })
public class Address {
;
@Column(name="CITY")
private String city ;
@Column(name="STATE")
private String state;
@Column(name="ZIP_POSTAL")
private String zipPostal ;
@Column(name="ADDRESS")
private String address
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID" unique = true, nullable = false)
private Integer id;
public String getAddress() { return address; }
@manyToOne
@JoinColumn(name="PERSON_ID", nullable=false)
private Integer person_id;
// getet and setter
}
- فرشته حقیقی 6 سال قبل پاسخ داد
فرض کنیم دو کلاس person و Address داریم که رابطه یک به چند (one to many) دارند. یعنی هر شخص می تواند چند آدرس داشته باشد.
CREATE TABLE PERSON (
ID integer identity primary key,
FIRST_NAME varchar(50) not null,
LAST_NAME varchar(50) not null,
CREATED timestamp,
CONSTRAINT IDX_PERSON_ID PRIMARY KEY (ID) );
CREATE TABLE ADDRESS (
ID integer identity primary key,
PERSON_ID integer,
ADDRESS varchar(255),
CITY varchar(50) not null,
STATE varchar(50) not null,
ZIP_POSTAL varchar(30) not null,
CREATED timestamp,
CONSTRAINT IDX_ADDRESS_ID PRIMARY KEY (ID),
CONSTRAINT FK_ADDRESS_PERSON_ID FOREIGN KEY (PERSON_ID) REFERENCES PERSON(ID) on delete cascade
);
.
در فایل xml مربوط به person در spring بصورت زیر عمل می کنیم:
Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.springbyexample.orm.hibernate3.bean" default-access="field">
<class name="Person" table="PERSON">
<id name="id" column="ID">
<generator class="native"/> </id>
<property name="firstName" column="FIRST_NAME" />
<property name="lastName" column="LAST_NAME" />
<set name="addresses" lazy="true" inverse="true">
<key column="PERSON_ID"/>
<one-to-many class="Address"/>
</set>
<property name="created" column="CREATED" />
</class>
</hibernate-mapping>
در فایل xml مربوط به address در spring نیز بصورت زیر عمل می کنیم:
Address.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.springbyexample.orm.hibernate3.bean" default-access="field">
<class name="Address" table="ADDRESS">
<id name="id" column="ID">
<generator class="native"/>
</id>
<property name="address" column="ADDRESS" />
<property name="city" column="CITY" />
<property name="state" column="STATE" />
<property name="zipPostal" column="ZIP_POSTAL" />
<property name="created" column="CREATED" />
</class>
<many-to-one name="Person" class="PERSON"
column="PERSON_ID" not-null="true"/>
</hibernate-mapping>
PERSON_ID دو جدول را به هم متصل می کند.
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
Generic Collection دیتا استراکچری می باشد که می توانیم در آن گروهی از ابجکتها قرار دهیم. Generic Collection ها در جاوا عبارتند از: List, Map,Set, Properties
در کلاس Collections متدهایی برای سینک کردن و غیرقابل تغییر نمودن کالکشن ها وجود دارد. سینک کردن یک کالکشن برای زمانی است که چند thread داریم و زمانیکه این تردها بصورت همزمان روی این کالکشن عملیاتی انجام می دهند خطایی به وجود نیاید. برای این اعمال بصورت زیر عمل می کنیم:
List< String > list1 = new ArrayList< String >();
List< String > list2 = Collections.synchronizedList( list1 );
List< String > list2 = Collections.unmodifiableList( list1 );
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
برای ایجاد تسکهای موازی به دو طریق می توانیم عمل کنیم:
- با استفاده از اینترفیس Runnable:
این اینترفیس یک متد run دارد که در آن عملیاتی که می خواهیم انجام دهیم را قرار می دهیم:
Public class Task implement Runnable{
Public void run()
{
//do something
}
}
- اجرا کردن آبجکتهای اینترفیس Runnable با استفاده از Executor:
Executor ترد ها را ایجاد و مدیریت می کند.
Public class taskExcute{
Public static void Mani(String[] args){
Task t1=new Task();
Task t2=new Task();
ExecutorSrevice e=Executors.newCachedThreadPool();
e.execute(t1);
e.execute(t2);
e.shutdown();
}
}
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
گاهی اوقات نیاز داریم تا یک وب سرویس را در برنامه خود فرخوانی کنیم.
برای فراخوانی یک سرویس rest به صورت زیر عمل می کنیم:
public <T> T call(Object requestData, Class<T> classOfT) throws Throwable {
T result = null;
try {
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader "Content-Type", "application/json; charset=UTF-8");
httpPost.setHeader("Accept", "application/json");
Header[] headers = new Header[httpPost.getAllHeaders().length];
for (int i = 0; i < httpPost.getAllHeaders().length; i++)
if (!httpPost.getAllHeaders()[i].getName().equalsIgnoreCase("authorization"))
headers[i] = httpPost.getAllHeaders()[i];
Date timeStamp = new Date();
byte[] sign = signer.sign(gson.toJson(new Object[]{timeStamp,
requestData}).getBytes());
httpPost.setHeader("sign", Base64.encodeBase64String(sign));
httpPost.setHeader("timestamp", gson.toJson(timeStamp));
- فرشته حقیقی 6 سال قبل پاسخ داد
برای کنترل فیلدها در struts دو روش وجود دارد:
- در کلاس اکشن فرم صفحه متد Validation قرار دهیم.
- در فایل Validation.xml فیلد مورد نظر را در تگ <field> اضافه کنیم:
<form name="formname”">
<field property=" company "
depends="maxlength,minlength, required " page="0">
<arg0 key=" fieldName"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<var>
<var-name>maxlength</var-name>
<var-value>4</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>3</var-value>
</var>
</field>
در فایل jsp فرم داریم:
<html:text property="company"/>
<bean:message key="fieldName" />
در اینجا بیان کردیم که ورود فیلد company
در فرم الزامی می باشد و
همچنین طول آن باید حداقل 3 و حداکثر 4 باشد.
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
Lambda بزرگترین ویژگی جاوا8 است. این ویژگی برنامه نویسی تابعی را سهولت می بخشد. سینتکس این عبارت بصورت زیر است:
Parameter -> expression body
مثلا یک تابع جمع بصورت زیر نوشته می شود:
( int x, int y) -> x+y
یا
(x,y) -> x+y
مهمترین ویژگی های این روش تابع نویسی عبارت است از:
- اعلان نوع متغیر اختیاری است: اعلان نوع پارامتر در متد اختیاری است و کامپایلر از مقدار پارامترها نوع آنها را استنتاج می کند.
- گذاشتن پرانتز دور پارامترها اختیاری است: اگر متد یک پارامتر داشته باشد میتوان پرانتز نگذاریم اما اگر چند پارامتر داشته باشیم باید پرانتز بگذاریم.
- اگر بدنه متد فقط یک خط داشته باشد نیازی نیست براکت گذاشته شود.
- اگر بدنه تنها یک عبارت برای برگرداندن مقدار داشته باشد نیازی به نوشتن کلمه return نیست و کامپایلر بصورت اتوماتیک آن مقدار را برمی گرداند. در این حالت براکت برای مشخص کردن عبارتی که باید یک مقدار را برگرداند لازم است.
همانطور که میبینیم با برداشتن محدودیت هایی مانند براکت و اعلان نوع پارامترها، متد نویسی بسیار آسانتر شده است.
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل
برای تبدیل تاریخ شمسی به میلادی متدی بصورت زیر تعریف میکنیم که ورودی های آن سال و ماه و روز شمسی می باشد.
public static int[] convertPersianToGregorian(int jalaly_year, int jalaly_month, int jalaly_day) {
int[] g_days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] j_days_in_month = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
int gy, gm, gd, g_day_no, j_day_no, jy, temp, jm, jd;
boolean leap;
jy = jalaly_year - 979;
jm = jalaly_month - 1;
jd = jalaly_day - 1;
j_day_no = 365 * jy + (jy / 33) * 8 + ((jy % 33 + 3) / 4);
for (int i = 0; i < jm; ++i)
j_day_no += j_days_in_month[i];
j_day_no += jd;
g_day_no = j_day_no + 79;
gy = 1600 + 400 * (g_day_no / 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
g_day_no = g_day_no % 146097;
leap = true;
if (g_day_no >= 36525) { /* 36525 = 365*100 + 100/4 */
g_day_no--;
gy += 100 * (g_day_no / 36524); /* 36524 = 365*100 + 100/4 - 100/100 */
g_day_no = g_day_no % 36524;
if (g_day_no >= 365)
g_day_no++;
else
leap = false;
}
gy += 4 * (g_day_no / 1461); /* 1461 = 365*4 + 4/4 */
g_day_no %= 1461;
if (g_day_no >= 366) {
leap = false;
g_day_no--;
gy += (g_day_no / 365);
g_day_no = g_day_no % 365;
}
temp = 0;
for (int i = 0; g_day_no >= g_days_in_month[i] + ((i == 1 && leap) ? 1 : 0); i++, temp = i)
g_day_no -= g_days_in_month[i] + ((i == 1 && leap) ? 1 : 0);
gm = temp + 1;
gd = g_day_no + 1;
GregorianCalendar gregorianDate = new GregorianCalendar(gy, gm - 1, gd);
int dayInWeek = gregorianDate.get(7);
dayInWeek += 1;
if (dayInWeek == 8) dayInWeek = 1;
return new int[]{gy, gm, gd, dayInWeek};
}
- فرشته حقیقی 6 سال قبل پاسخ داد
- آخرین فعالیت در 6 سال قبل