Hibernate =========================================================== Books: Java Persistence with Hibernate Database Manipulation ----------------------------------------------------------- Process of retrieveing objects * Search in the Session Cache. * Search in the "NonExists" record * Search in the sessionFactory Cache if it could. * Select SQL, (add the infomation in the "NonExists" record if object not exsist, and return null.) * Use the ResultSet to get the obejct. * Bring the object to Session Cache. * Excute the Inteceptor.onLoad(). * Bring the object to Session Factory Cache. * Excute the onLoad() if obejct has implemented the LifeCycle interface. * Return the object. get() and load() * if the object not exsist, Null will be returned by get(), and ObjectNotFoundException by load(). * load() could return a proxy class and use the sessionFactory cache. find() and iterate() * Hibernate 2 's Query and Criteria are based on these two methods, Session.find() equals Session.createQuery.list(), Session.iterate() equals Session.createQuery.iterate() in version 3. save(), update() and saveOrUpdate() list() uniqueResult() Priciple ----------------------------------------------------------- Instance states * transient (has no persistent identity) * persistent (has a persistent identity and, perhaps, a corresponding row in the database,guarantees that persistent identity is equivalent to Java identity) * detached (has a persistent identity and, perhaps, a corresponding row in the database, no guarantees about the relationship between persistent identity and Java identity) * switch |--------------------------------- END (garbage collection)--------------------------------- | save(), saveOrUpdate() close(), evict(), clear() | @---new()--> transient <===========================> persistent <==============================> detached--- | delete() | update(), saveOrUpdate() | get(), load(), find(), iterator(), list()... | |-------------------------------------------------------- * Judge states of transientg and detached - id unsaved-value - version - if Interceptor.isUnsaved return True * PO(persistence object) vs VO (value object) Judge: if managed by Entity Map Extends: VO as a DTO(Data Transfer Object) Usage: Apache Jakarta Commons Beanutils to copy properties. (throws IllegalAccessExcpetion) Object identify and equality * compare with memory address ("==") * compare with infomation (equals() and hashCode()) we have to override the equals() nad hashCode() methods if we intend to put instansts of persistence classes in a Set and intend to use reattchement of detatched instances. Dirty Data Checking(Two ways) -- 1. Checking the data object (Check the setter methods by Dynamic Proxy Pattern or CGLIB) -- 2. Compare with data version (Adopted by Hibernate) public void commit() throws HibernateException(){ ...... if( session.getFlushMode()!= FlushMode.NEVER) session.flush(); //flushEverything(); ...... } Attribution of EntityEntry -- loadedState. Data Cache Strategy * Transaction level Cache * Application/Process level Cache * Cluster level cache * Cache in Hibernate: - use the identifier to load data. (Session.load(), Session.iterate()) - Lazy-init - Session Level (Session.evict, Session.clear) - SessionFactory Level (support a simple Hashtable [org.hibernate.cache.HashtableCacheProvider], third party cache: JCS, EHCache, OSCache, JBoss Cache, SwarmCache) Transactions and Concurrency * ACID (Atomic, Consistency, Isolation, Durability) * Based on JDBC session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); ...... tx.commit(); Connection conn = getConnection(); conn.setAutoCommit(false); // AutoCommit has been set to false when openSession(), so if no transaction, the save() method will not // affect the db(support tranaction) ...... conn.commit(); * Based on JTA (Java Transaction API,UserTransaction, TransactionManager, Transaction) JTA can span many connections or sessions. Session.beginTransaction have call the IntitialContext.lookup() Easy to use JTA in EJB, because there is no need to call transaction manager in the code. Concurrency Locking * Pessimistic Locking (use the "for update" statement) String hqlStr = "from Student as stu where stu.name = 'lidnux'" Query query = session.createQuery(hqlStr); query.setLockMode("stu", LockMode.UPGRADE); query.list(); * LockMode // LockMode.NONE LockMode.WRITE LockMode.READ LockMode.UPGRATE LockMode.UPGRATE_NOWAIT * Set the LockMode Criteria.setLockMode Query.setLockMode Session.lock * Optimistic Locking Relationship ----------------------------------------------------------- id * Generator increment/identify/sequence/hilo/seqhilo/uuid/guid/native/assigned/select/foreign/sequence-identify One-to-One association (two varieties) -- 1. primary key association (A special Hibernate identifier generation strategy called foreign) * Add mappings one-to-one association has no column element, we can specify it in id element. * Use identifier generation student * Use in code student.setCertificate(certificate); cerfificate.setStudent(student); //requeried StudentDAO.save(student); //cascade save -- 2. unique foreign key association (many-to-one association with unique element to make bidirectional association) * Add mappings Many-to-Many association Query ----------------------------------------------------------- Criteria Query * Narrowing the result set List students = session.createCriteria() .add( Restrictions.like("name", "lidnux%")) .add( Restrictions.between("weight", minWeight, maxWeight)) .list(); Built-in criterion types; To specify SQL directly: // {alias} placeholder with be replaced by the row alias of the queried entity. .add( Restrictions.sqlRestriction("lower({alias}.name) like lower(?)", "Lidnux%", Hibernate.STRING) ) To get a criterion from a Property instance Property age = Property.forName("age"); List students = session.createCriteria(Student.class) .add( Restrictions.disjunction() .add( age.isNull() ) .add( age.eq( new Integer(0) ) ) .add( age.eq( new Integer(1) ) ) .add( age.eq( new Integer(2) ) ) ) ) .add( Property.forName("name").in( new String[] { "Lidnux", "Lidanux", "Dan" } ) ) .list(); * Ordering the results .addOrder( Order.asc("name") ) .addOrder( Order.desc("age") ) .setMaxResults(50) .list(); .add( Property.forName("name").like("F%") ) .addOrder( Property.forName("name").asc() ) .addOrder( Property.forName("age").desc() ) .setMaxResults(50) .list(); * Associations List teams = sess.createCriteria(Team.class) .add( Restrictions.like("name", "03242%") ) .createCriteria("students") //return a new instance of Criteria,which refers to the elements of the student collection. .add( Restrictions.like("name", "lidnux%")) .list(); In certain circumstances, this method is useful List teams = session.createCriteria(Team.class) .createAlias("students", stu) .add(Restrictions.like(stu.name,"lidnux%") .list(); Native SQL