Hibernate Notes.docx

March 14, 2018 | Author: Sankar Susarla | Category: Databases, Data Type, Relational Model, Data Model, Inheritance (Object Oriented Programming)
Share Embed Donate


Short Description

hibernate...

Description

1 1What is Hibernate? • Hibernate is an open source project to provide a powerful, high performance object/relational persistence and query service. • Hibernate generates SQL for you relieves you from manual JDBC result Ser handling and object conversion, and keeps you application portable to all SQL databases. • Hibernate provides transparent persistence, the only requirement for a persistent class is a no argument constructor. • Hibernate offers sophisticated query options you can write plain SQL, object-oriented HQL(Hibernate Query Language), or create programmatic Criteria an example queries(QBE). • Hibernate can optimize object loading all the time, with various fetching and caching opetions. • Hibernate’s goal is to reliev the developer from 95 percent of common dta persistence related programming tasks, compared to manual coding with SQL and the JDBC API.

Hibernate architecture has three main components: • Connection Management Hibernate Connection management service provide efficient management of the Databaseconnections. Database connection is the most expensive part of interacting with the database as it requires a lot of resources of open and close the database connection. • Transaction management: Transaction management service provide the ability to the user to execute more than one database statements at a time. • Object relational mapping: Object relational mapping is technique of mapping the data representation from an object model to a relational data model. This part of the hibernate is used to select, insert, update and delete the records form the underlying table. When we pass an object to aSession.save() method, Hibernate reads the state of the variables of that object and executes the necessary query. An application using Hibernate contains the following components Hibernate Configuration file Either this is an XML file called hibernate.cfg.xml or a properties file called – hibernate.properties. Properties defined in the configuration file specify the following • Database properties • Entity classes to be managed by Hibernate • SQL dialect- how to convert HSQL to native SQl • Other properties related to caching etc. org.hibernate.dialect.OracleDialect oracle.jdbc.OracleDriver jdbc:oracle:thin:@localhost:1521:xe hr hr true update

2 Entity Classes These classes are nothing but POJO (plain Old Java Object). Its field are mapped to columns in a row in table. Either you can declare these classes in mapping file or use annotations, to declare metadata. Each object of this class must have an id (Primary key0, which is used to uniquely identify the object import java.util.Date; public class User { private String uname,email,mobile; private Date dob; public User() { } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } } Mapping files These files are xml files used to specify object Relation mapping (ORM) these files are to be listed in hibernate configuration file or added to configuration object using addResource() method of configuration object. Configuration object An instance of configuration represents an entire set of mapping of an applications. Java types to an SQL database. The Configuration is used to build an (immutable)SessionFactory. The Mapping are compiled from various XML files Session Factory object A thread safe(immutable) cache of compiled mappings for a simple database. A factory for Session and a client of ConnectionProvider. Might hold an optional(second-level) cache of data that is resalable between transactions, at a process-level or cluster-level Session object A single-treaded, short-lived object representing a conversation between the application and the persistent store. Wraps a JDBC connection . Factory for Transitions. Holds a mandatory(first-level)cache of persistent objects used when navigating the object graph or looking up objects by identifier . All operations related to persistence are done using methods in session object. Session objects is created from Session Factory object, which in turn is created from Configuration class AddUser.jap import java.util.Date; import org.hibernate.*; public class AddUser { public static void main(String[] args) throws Exception { Configuration cfg=new Configuration().configure(); SessionFactory sf=cfg.buildSessionFactory(); Session session=sf.openSession(); User u=new User(); u.setUname("abc"); u.setEmail("[email protected]"); u.setMobile(“1234567890”); u.setDob(new Date()); session.beginTransaction(); session.save(u); session.getTransaction().commit(); session.close(); sf.close(); } }

3 Persistent Objects and collection Short-lived, single threaded objects containing persistent state and business function. These might be ordinary JavaBeans/POLJS, the only special thing about them is that they are currently associated with (Exactly one )i Session . As soon as the session is closed, they will be detached and free to use in any application layer(e.g directly as data transfer object to and from presentation). Transient and detached objects and collections instance of persistent classes those are not currently associated with a session. They may have been instantiated by the application and not(yet) persisted or they may have been instantiated by a closed session. Transaction A single-threaded, short-lived object used by the application to specify atomic units of work, abstracts application from underlying JDBC,JTA or CORBA transaction. A Session might span several Transaction in some cases. However, transaction demarcation, either using the underplaying API or Transaction is never optional. import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class ListUsers { public static void main(String[] args) throws Exception { Configuration cfg=new Configuration().configure(); SessionFactory sf=cfg.buildSessionFactory(); Session session=sf.openSession(); Query q=session.createQuery("from User"); List l=q.list(); for(Object o:l){ User u=(User) o; System.out.println(u.getUname()+":"+u.getEmail()+":"+u.getMobile()+":"+u.getDob()); } } }

Methods of configuration information user one of the following methods Method Description Configure() Use the mappings and properties specified int eh application resource named hibernate.cfg.xml Confgirue(File Use the mapints and properties specified int eh given application file configfile) Confgirue(String Use the mappings the properties specified in the given application resoruce) Configuret(URL url Use the mappings and properties specified int eh given document. Or

Configuration cfg=new Configuration();

cfg.configure(“hibernate.cfg.xml); Addition mapping fiels You can add mapping document using hibernate configuration file. An alternative (sometimes better) way is to specify the mapped class and let Hibernate find the mapping document for you. You can use one of the following methods of configuration object to load mapping files. Method addClass(Class class) addDirectory(File dir) addFile(File xmlFile addFile(String xmlFile) addResouce(String

Description Read a mapping as an application resource using the convention that a class named st.Title is mapped by a file st/title.hml.xml which can be resolved as a classpath resource. Read all maping documents from a directly tree. Read mappings from a particular XML File Read mappings from a particular XML file Read mappings from the specified resource(file

4 resource) Configuratio cfg=new Configuration().addResource(“title.hbm.xml”).addResource(“author.hbm.xml”); Configuration cfg=new Configuration().addClass(Title.class).addClass(Author.class); JDBC connection properties Usually, you want to have the SessionFactory to be created and pool JDBC connections. As soon as you do something that requires access to the database, a JDBC connection will be obtained from the pool For this to work, we need to pass some JDBC connection properties to Hibernate. hibernate.connection.driver_class oracle.jdbc.OracleDriver hibernate.connection.url Jdbc URL hibernate.connection.username Database user nam hibernate.connection.password Database user password hibernate.connection.pool_size

SQL Dialects

You should always set the hibernate.dialect property to the correct org.hibernate.dialect.Dialect subclass for your database. • DB2 - org.hibernate.dialect.DB2Dialect • HypersonicSQL - org.hibernate.dialect.HSQLDialect



Informix - org.hibernate.dialect.InformixDialect



Ingres - org.hibernate.dialect.IngresDialect



Interbase - org.hibernate.dialect.InterbaseDialect



Pointbase - org.hibernate.dialect.PointbaseDialect



PostgreSQL - org.hibernate.dialect.PostgreSQLDialect



Mckoi SQL - org.hibernate.dialect.MckoiDialect



Microsoft SQL Server - org.hibernate.dialect.SQLServerDialect



MySQL - org.hibernate.dialect.MySQLDialect



Oracle (any version) - org.hibernate.dialect.OracleDialect



Oracle 9 - org.hibernate.dialect.Oracle9Dialect



Progress - org.hibernate.dialect.ProgressDialect



FrontBase - org.hibernate.dialect.FrontbaseDialect



SAP DB - org.hibernate.dialect.SAPDBDialect



Sybase - org.hibernate.dialect.SybaseDialect



Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect

Understanding Hibernate O/R Mapping Hibernate mapping documents are simple xml documents. Here are important elements of the mapping file:. 1. element The first or root element of hibernate mapping document is element. Between the tag class element(s) are present. 2.

element The element maps the class object with corresponding entity in the database. It also tells what table in the database has to access and what column in that table it should use. Within one element, several mappings are possible.

3.

element The element in unique identifier to identify and object. In fact element map with the

5 primary key of the table. In our code : primary key maps to the ID field of the table CONTACT. The attributes of the id element are: • name: The property name used by the persistent class. • column: The column used to store the primary key value. • type: The Java data type used. • unsaved-value: This is the value used to determine if a class has been made persistent. If the value of the id attribute is null, then it means that this object has not been persisted. 4.

element The method is used to generate the primary key for the new record. Here is some of the commonly used generators * Increment - This is used to generate primary keys of type long, short or int that are unique only. It should not be used in the clustered deployment environment. * Sequence - Hibernate can also use the sequences to generate the primary key. It can be used with DB2, PostgreSQL, Oracle, SAP DB databases. * Assigned - Assigned method is used when application code generates the primary key.

5.

element The property elements define standard Java attributes and their mapping into database schema. The property element supports the column child element to specify additional properties, such as the index name on a column or a specific column type.

Persistent classes

Persistent classes are classes in an application that implement the entities of the business problem(e.g. customer and Order in an E-commerce application). Hibernate works best if these classes follow some simple rules, also known as the plain OLD Java Object(POJO) programming model, However none of these rules are hard requirements. Indeed, Hibernate3 assumes very little about the nature of your persistent objects. • All persistent classes must have a default constructor. • All persistence classes must have an identifier property. This property maps to the primary key column of a database table. • You have to override the equals() and hashCode() methods if you o Intend to put instances of persistent classes in a set and o Intend to use reattachment of detached instances

Session interface The lifecycle of a Session is bounded by the beginning and end of a logical transaction. (Long transactions might span several database transactions.) The main function of the Session is to offer create, read and delete operations for instances of mapped entity classes. Instances may exist in one of three states: transient: never persistent, not associated with any Session persistent: associated with a unique Session detached: previously persistent, not associated with any Session • •

The lifecycle of the session is bounded by the beginning and end of a logical transaction Transient instances may be made persistent by calling save(),persist() or saveOrUpdate()



Persistent instances may be made transient by calling delete()



Any instance returned by a get() or load() method is persistent



Detached instances may be made persistent by calling update(),svaeOrUpdate(),lock() or replicate()



The state ofa transient or detached instance may also be make persistent as a new persistent instance by calling merge()



Methods save() and persist() result in a SQL insert, delete() in an SQL DELETE and update() or merge() in an SQL UPDATE.



Changes to persistent instances are detected at flush times and also result in an sql UPDATE.

6 •

Method saveOrUpdate() and replicate() result in either an INSERT or an UPDATE.

Transaction beginTransaction() void cancelQuery() Connection close() boolean contains(Object object) Criteria createCriteria(Class persistentClass) Query createFilter(Object collection, String queryString) Query createQuery(String queryString) SQLQuery createSQLQuery(String queryString) void delete(Object object) void evict(Object object) void flush() Object get(Class clazz, Serializable id Query getNamedQuery(String queryName) SessionFactory getSessionFactory() Transaction getTransaction() boolean isOpen() boolean isDirty() Object load(Class theClass, Serializable id) Object merge(Object object) void persist(Object object) void refresh(Object object) Serializable save(Object object void saveOrUpdate(Object object)

void setCacheMode(CacheMode cacheMode void update(Object object)

Begin

a

unit

of

work

and

return

the

associated

Transaction object. Cancel the execution of the current query. End the session by releasing the JDBC connection and cleaning up. Check if this instance is associated with this Session. Create a new Criteria instance, for the given entity class, or a superclass of an entity class. Create a new instance of Query for the given collection and filter string. Create a new instance of Query for the given HQL query string. Create a new instance of SQLQuery for the given SQL query string. Remove a persistent instance from the datastore. Remove this instance from the session cache. Force this session to flush. Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. Obtain an instance of Query for a named query string defined in the mapping file. Get the session factory which created this session. Get the Transaction instance associated with this session. Check if the session is still open. Does this session contain any changes which must be synchronized with the database? In other words, would any DML operations be executed if we flushed this session? Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. Copy the state of the given object onto the persistent object with the same identifier. Make a transient instance persistent. Re-read the state of the given instance from the underlying database. Persist the given transient instance, first assigning a generated identifier. Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking). Set the cache mode. Update the persistent instance with the identifier of the given detached instance.

7 new

get() load()

save() saveOr Update( ) evict() close() clear()

garbage

Transient delete() Persistent

update() saveOtrUpdate() lock()

Detached

garbage

Making object persistent • Newly instantiated instance of an entity are considered transient by Hibernate. • We can make a transient instance persistent by a associating it with a session as follows Person person=new Person() person.setName(“Siva Prakash”); session.save(person);

Loading an object • •

Each load(..)method requires object’s primary key as an identifier Each load(..) method also requires which domain class or entity name to use to find the object with the id • The returned object, which is returned as object type, needs to be type-case to the domain class load() vs.get() • Use the load() method if you are sure that the object exists. Load() method will throw an exception if the unique id is not found in the database. • If you are not sure that the object exists, then use one of the get() methods, which returns null if object is not found in the database • Updating object Updating object • Hibernate automatically manages any changes made to the persistent objects • If a property changes on a persistent object, Hibernate session will perform the change in the database • You can force Hibernate to commit all of its changes using flush() method. • You can also determine if the session is dirty through isDirty() method. Transaction tx=session.beginTransaction(); Person person=(Person)session.load(Person.class,new Integer(1)); person.setName(“Siva Prakash”); tx.commit(); Refreshing Objects • Use refresh() method to refresh objects from their database representations in cases where there is a possibility of persistent object is not in sync. With the database representation. • Scenarios you might want to do this; you hibernate application is not the only application working with this data, you applications executes some SQL directly against the database • You database uses triggers to populate properties on the object Deleting objects • Use delete() method to remove an object from the database. • Your application might still hold a reference to a deleted object. • It’s best to think of delete() as making a persistent instance transient. Life-cycole Operations and SQL commands • save() and persist() result in an SQL INSERT • delete() result in an SQL DELETE • update() or merge() result in an SQL UPDATE • changes to persistent instances are detected at flush time and also result in an SQL UPDATE • saveOrUpdate() and replicate() result in their an INSERT or an UPDATE Cascading Operations • lifecycle operations can be cascaded

8 •

cascading configuration flag(specified in the mapping update,evict,replicate,lock,refresh

file)-persist,merge,delete,save-

Transaction interface • it allows the applications to define units of work, while maintaining abstraction from the underlying transaction implementation(ex.JTA select * from allstudents; SNO STYPE NAME PMARKS TOT ---------------------------- ------------------1 Science rams 110 250 2 Arts krish 575

Table per sub class In this inheritance is represented using foreign key association. Every class/subclass that has persistent properties(including abstraction classes) has its own table. Table related to subclasses are related to super class table using foreign foreign key in subclass table. • Schema is normalized • Queries require a join across many tables • Performance may be unacceptable for complex class hierarchies.

tpersubclass_seq create sequence tpersubclass_seq start with 2000 increment by 1 nocache;

13

SQL> select * from Schoolstudents; SNO NAME --------------------------------1 rams 2 krish SQL> select * from science; SNO PMARKS TOT ---------- ---------- ---------1 110 250 SQL> select * from arts; SNO TOT ---------- ---------Table per concrete class 2 575

A table • • • •

is created with all the properties(including inherited for each concreate class. Queries against superclass must be executed on several table related to concrete subclasses. Queries against subclasses perform well A change to super class property needs a change to subclass tables Difficult to implement integrity constraints

SQL> select * from onlyscience; SNO NAME PMARKS TOT ---------- ---------- ---------- ---------41 rams 110 250 SQL> select * from onlyarts; SNO NAME TOT ---------- ---------- ---------42 krish 575

Associations

Relationships between entities form the crux of the relational approach. This must be well reflected by an ORM framework. In the world of the object-oriented approach, relations between objects are represented by associations. So the task of any ORM framework is to create a mapping between the relationships and the associations. This mapping is known as an association. The term is the same as that of the object oriented approach. Hence this discussion will focus on both the life-cycle states of persistent objects and associations. The first section will deal with the life-cycle of the persistent object. In the second section I will discuss associations. The third section will put the concepts to work, as I will extend the application which was being developed during previous parts to include one more table with a

14 many to one relationship with the order table. Now that the agenda has been disclosed, l will get right into the topic. Relationship between entities can be classified into one-to-many/nay-to-one and many –to- many. Employee.java

package onetoone;

Relationship be unidirectional, where only one entity references the other, order bidirectional, where public classmay Employee { eachprivate entity references the other. int id;

private String name;

Unidirectional one-to-one private LibraryMemebership membership;

//create a property of id, string memebrship

In} this there is one-to-one relational between entities and only one entity references the other. relationship is represented by a foreign LibraryMemebrship.java key in a table.

The

package onetoone; import (1) name:org.hibernate.cfg.Configuration; The name of the property. (2) classclass (optional - defaults to the property type determined by reflection): The name of the associated public UniOneToOneDemo { class. public static void main(String[] args) throws Exception { (3) cascade (optional) specifies which operations should be cascaded from the parent object to the // TODO code application logic here associated object. Configuration cfg = new Configuration().configure(); (4) constrained (optional) specifies that a foreign key constraint on the primary key of the mapped table //cfg.addResource("onttoone/uni_onetoone.hbm.xml"); references the table of the class. This option affects the order in which save() and delete() are Session session = associated cfg.buildSessionFactory().openSession(); cascaded, and determines whether the session.beginTransaction(); association may be proxied (it is also used by the schema export tool). Employee e = new Employee(); (5) fetch (optional - defaults to select): Chooses between outer-join fetching or sequential select fetching. e.setName("prakash"); (6) property-ref: (optional) The name of a property of the associated class that is joined to the primary key of LibraryMembership lmprimary = newkey LibraryMembership(); this class. If not specified, the of the associated class is used. lm.setType("Normal"); (7) access (optional - defaults to property): The strategy Hibernate should use for accessing the property value. e.setMembership(lm); session.save(e); (8) formula (optional): Almost all one to one associations map to the primary key of the owning entity. In session.getTransaction().commit(); the rare case that this is not the case, you may specify a some other column, columns or expression to join //retrieve employees on using an SQL formula. List listemployees = session.createQuery("from Employee e").list(); for (Object o : listemployees) { e = (Employee) o; System.out.println(e.getName()+":"+e.getMembership().getType()); } session.close(); } } uni_onetoone.hbm.xml

15

Employee.java package by_onetoone; public class Employee { private int id; private String name; private LibraryMembership membership; //create a property } LibraryMembership.java package by_onetoone; public class LibraryMembership { private int id; private String type; private Employee employee; //create a property } OneToOneDemo.java package by_onetoone; import java.util.List; import org.hibernate.Session; import org.hibernate.cfg.Configuration; public class OneToOneDemo { public static void main(String[] args) throws Exception { // TODO code application logic here Configuration cfg = new Configuration().configure(); //cfg.addResource("onttoone/uni_onetoone.hbm.xml"); Session session = cfg.buildSessionFactory().openSession(); session.beginTransaction(); Employee e = new Employee(); e.setName("siva"); LibraryMembership lmember = new LibraryMembership(); lmember.setType("Normal"); Bidirectional One-to-One e.setMembership(lmember); lmember.setEmployee(e); In bidirectional one-to-one association, two entities reference each other with a property in each session.save(e); session.getTransaction().commit(); //retrieve employees List listemployees = session.createQuery("from Employee").list(); for (Object o : listemployees) { e = (Employee) o; System.out.println(e.getName()+":"+e.getMembership().getType()); } List lismembership = session.createQuery("from LibraryMembership").list(); LibraryMembership l; for (Object o : lismembership) { l = (LibraryMembership) o; System.out.println(l.getId()+":"+l.getEmployee().getName()); } session.close(); } }

16

Department.java package manytoone; import java.util.HashSet; import java.util.Set; public class Department { private int id; private String name; private Set employees=new HashSet(); //create a progperty of the id,name,employees; } Employee.java package manytoone; public class Employee { private int id; private String name; private Department department; //create property of id,name,department } manytoone.hbm.xml Bidirectional one-to-many and many-to-one In this many-side with a foreign key in manyside table.

17

package manytoone; import java.util.List; import org.hibernate.*; import org.hibernate.cfg.Configuration; public class ManyToOneDemo { public static void main(String[] args) throws Exception { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); SessionFactory sf = cfg.buildSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Employee e1 = new Employee(); e1.setName("abc"); Employee e2 = new Employee(); e2.setName("xyz"); Department d = new Department(); E1 d.setName("Testing"); e1.setDepartment(d); departement e2.setDepartment(d); E d.getEmployees().add(e1); 2 d.getEmployees().add(e2); session.save(d); session.save(e1); session.getTransaction().commit();

session.save(e2);

List lemp = session.createQuery("from Employee e").list(); System.out.println(lemp.size()); for(Object o:lemp){ e1=(Employee)o; System.out.println(e1.getId()+":"+e1.getName() +":"+e1.getDepartment().getName()); } List ldept = session.createQuery("from Department d").list(); for(Object o:ldept){ d=(Department)o; for(Employee emp:d.getEmployees()) System.out.println(emp.getId()+":"+emp.getName()+":"+emp.getName()); } session.close(); } }

18

Bidirectional many-to-many Bidirectional many-to-many is represented with a join table. Join table contains two columns- one references firt entity and another references second table.

package manytomany; import java.util.HashSet; import java.util.Set; public class Employee { private int id; private String name; private Set projects=new HashSet(); . //create a property of id,name,projects }

package manytomany; import java.util.HashSet; manytomany.hbm.xml import java.util.Set; public class Project { private int id; private String title; private Set employees=new HashSet(); . //create a property ofname="projects" id,title,employeestable="EmployeeProjects"> =,500 From Title where title like’Pro%’ From Title where instr(title,’Asp’)>0 Select t.title||’-‘||t.price from Title t Select max(price)from Title Select t.subject.subname,max(t.price)from Title group by t,.subject.subname From Titlet.join t.subject s with s.subcode=’java’ From Title t where t.price is not null From Title t where t.subject.subcoe in (‘java’,’C#);] From Title t where t.price=(select max(t.price) from Title t);

23 Query interface

• •

An object-oriented representation of a Hibernate query. A Query instance is obtained by calling Session.createQuery(). This interface exposes some extra functionality beyond that provided by Session.iterate() and Session.find():

A particular page of the result set may be select by calling setMaxResults(),setFirstRetult() Named query parameters are tokens of the form :name in the query string. A value is bound to the integer parameter :foo by calling • You may not mix and match JDBC-style parameters and named parameters in the same query. • Query are executed by caling list(),scroll(0or iterate(). A query may be re-executed by subsequent invocations. Its lifespan is , how ever bounded by the lifespan of the session that created. int executeUpdate() Execute the update or delete statement. List list() Return the query results as a List. String getQueryString() Get the query string. Iterator iterate() Return the query results as an Iterator. ScrollableResults scroll() Return the query results as ScrollableResults. Query Bind a value to a JDBC-style query parameter. setParameter(int position, Object val) Query setEntity(int position, Bind an instance of a mapped persistent class to a Object val) JDBC-style query parameter. Query Set a fetch size for the underlying JDBC query. setFetchSize(int fetchSize) Query Set the first row to retrieve. setFirstResult(int firstResult) Object uniqueResult() Convenience method to return a single instance that



matches the query, or null if the query returns no results. Bulk updates Hibernate provides methods for bull SQL – style DML statements execution which are performed through the Hibernate Query Language (UPDATE | DELETE ) [FROM] ENTITYnAME [(WHERE WHER_CONDITION)} There can only be a single entity named in the from clause; it can optionally be aliased. If the entity named is aliased, then any property references must be qualified using that alias. package query;

import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class BulkUpdates { public static void main(String[] args) throws Exception { // TODO code application logic here Configuration cfg = new Configuration().configure(); //cfg.configure("query/hibernate.cfg.xml"); //cfg.addResource("query/catalog.hbm/xml"); Session session = cfg.buildSessionFactory().openSession(); session.beginTransaction(); Transaction tx = session.getTransaction(); Query q = session.createQuery("update Title set price=price-50 where price
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF