Thursday, March 31, 2016

Spring AOP

AOP aspect oriented programming


Normally like security check, transaction, log, these commonly used functions are not related to business logic, we can use proxy to separate these code from business codes

Dynamic Proxy
AOP is done in theory of Dynamic Proxy
To understand how and why Dynamic Proxy works: 


Advice implements Aspect

Pointcut(add*): only apply on function name of add*


To see this Spring AOP with AspectJ with no Annotation Config(newer Version)
http://gvace.blogspot.com/2016/04/spring-aop-with-aspectj-no-annotation.html

To see Spring AOP with annotation(newer Version):
http://gvace.blogspot.com/2016/04/spring-aop-with-annotation.html

beans

Target Objects
Advice class
Proxy


Procedure
  1. define interface
  2. target bean class
  3. Advice class
  4. beans xml config
  5. config target bean
  6. config advice
  7. config proxy

Advice types
Advice typeInterfaceDescription
Aroundorg.aopalliance.intercept.MethodInterceptorIntercept target method
Beforeorg.springframework.aop.MethodBeforeAdviceCall before target method
Afterorg.springframework.aop.AfterReturningAdviceCall after target method returns
Throwsorg.springframework.aop.ThrowsAdviceCall when target method throws exception
Function Filter by Nameorg.springframework.aop.support.NameMatchMethodPointcutAdvisorApply only on function with the matched name



Advice order:
  1. MethodBeforeAdvice
  2. MethodInterceptor
  3. target method
  4. MethodInterceptor
  5. AfterReturningAdvice



ProxyFactoryBean:
Only need to setup, does not need code, use dynamic proxy instead
each ProxyFactoryBean only targets to one existed bean
  • proxyInterfaces: register interceptor on all functions of each interface
  • interceptorNames: register advice to run before/after all functions in proxyInterfaces
  • target: has to be only one existed bean


MethodInterceptor
Remember to get method return value, and return the value.

Example:
public class MyMethodInterceptor implements MethodInterceptor{
 
 /**
  * @methodInvocation
  * @return return what methodInvocation returns
  */
 @Override
 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  System.out.println("Before method invote "+methodInvocation.getMethod().getName());
  Object returnValue = methodInvocation.proceed();
  System.out.println("After method invote "+methodInvocation.getMethod().getName());
  return returnValue;
 }
 
}


ThrowsAdvice
Run when there is an error

ThrowsAdvice is just a flag, no function required to implement
Create either one of the following functions by yourself(See from example)
If created both, it always just run the one with multiple arguments


Example:
public class MyThrowsAdvice implements ThrowsAdvice{
 /*
  * ThrowsAdvice is just a flag, no function required to implement
  * Create either one of the following functions by yourself
  * 
  * If created both, it always just run the one with multiple arguments
  */
 public void afterThrowing(Throwable throwable){
  System.out.println("******Something WRONG!!!!!"+throwable.getMessage());
 }
 public void afterThrowing(Method m, Object[] os, Object target, Exception throwable){
  System.out.println("Something WRONG!!!!!"+throwable.getMessage());
 }
}



NameMatchMethodPointcutAdvisor
Like a Filter: apply only on function with the matched name(support regular expression)
Referenced on another Advice, and filter its function by matched name
So the referenced Advice does not need to register in the proxy, use this Filter instead
Just config, do not need implementation

Example:
<bean id="myMethodBeforeAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
 <property name="advice" ref="MyMethodBeforeAdvice" />
 <property name="mappedNames">
  <list>
   <value>sayBye</value>
  </list>
 </property>
</bean>



Whole Process Example

  1. define interface
    public interface TestServiceInterface {
     public void sayHello();
    }
    public interface TestServiceInterface2 {
     public void sayBye();
    }
    
  2. target bean class
    public class Test1Service implements TestServiceInterface, TestServiceInterface2{
     private String name;
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     @Override
     public void sayHello() {
      System.out.println("Hello "+name);
     }
     @Override
     public void sayBye() {
      System.out.println("Bye "+name);
     }
    
    }
    
  3. Advice class
    public class MyMethodBeforeAdvice implements MethodBeforeAdvice{
     /**
      * @method target method
      * @args parameters of target method
      * @target target object
      */
     @Override
     public void before(Method method, Object[] args, Object target) 
       throws Throwable {  //method.invoke(target, args);
      System.out.println("Log"+method.getName());
     }
     
     
    }
    
  4. beans xml config
  5. config target bean
  6. config advice
  7. config proxy
  8. <!-- target objects -->
    <bean id="test1Service" class="com.gvace.aop.Test1Service">
     <property name="name" value="service1"></property>
    </bean>
    
    <!-- Method Before Advice -->
    <bean id="MyMethodBeforeAdvice" class="com.gvace.aop.MyMethodBeforeAdvice"></bean>
    
    <!-- Proxy Object -->
    <bean id="ProxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
     <!-- config Target Object -->
     <property name="target" ref="test1Service" />
     <!-- Proxy Interface collection -->
     <property name="proxyInterfaces">
      <list>
       <value>com.gvace.aop.TestServiceInterface</value>
       <value>com.gvace.aop.TestServiceInterface2</value>
      </list>
     </property>
     <!-- Insert Advice into proxy object -->
     <property name="interceptorNames">
      <!-- link Advices with ProxyFactoryBean -->
      <list>
       <value>MyMethodBeforeAdvice</value>
      </list>
     </property>
    </bean>
    





























Sunday, March 27, 2016

Spring Provided beans

Spring Provided beans
BeanPostProcessor Interface
BeanFactoryPostProcessor Interface
BeanNameAware
BeanFactoryAware
ApplicationContextAware

These beans related to :Spring Bean Life Cycle



org.springframework.beans.factory.config.PropertyPlaceholderConfigurer

Set properties from a properties file. Use placeholder ${} ref  to property name

Set <bean> PropertyPlaceholderConfigurer, or use <context:property-placeholder>

Notice: only work in ApplicationContext. Does NOT work with BeanFactory

<!-- Use PropertyPlaceholderConfigurer as a bean -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 <property name="locations">
  <list>
   <value>com/gvace/dispatch/db.properties</value>
   <value>com/gvace/dispatch/db1.properties</value>
  </list>
 </property>
</bean>
<!-- Or use <context:property-placeholder>
<context:property-placeholder location="classpath:com/gvace/dispatch/db.properties, classpath:com/gvace/dispatch/db1.properties"/>
-->
<bean id="dbutil" class="com.gvace.dispatch.DBUtil" >
 <property name="drivername"><value>${drivername}</value></property>
 <property name="url" value="${url}"></property>
 <property name="username" value="${username}"></property>
 <property name="pwd" value="${pwd}"></property>
</bean>

Saturday, March 26, 2016

Spring Autowire

Spring IoC container can autowire relationships between beans.

<bean id="owner" class="com.gvace.autowire.Owner" autowire="byName">
...
</bean>

autowire modes
  1. no
  2. byName
  3. byType
  4. constructor
  5. autodetect
  6. default
attributes
  1. primary
  2. autowire-candidate


Example

public class Owner {
 private String name;
 private Dog dog;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Dog getDog() {
  return dog;
 }
 public void setDog(Dog dog) {
  this.dog = dog;
 }
 
}
public class Dog {
 private String name;
 private int age;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
}


no
Default is no
No autowire

byName

Since owner's property name is "dog", Spring will look for bean with id "dog"


<bean id="owner" class="com.gvace.autowire.Owner" autowire="byName">
 <property name="name" value="ownerA"></property>
</bean>
<bean id="dog" class="com.gvace.autowire.Dog">
 <property name="name" value="dogB"></property>
 <property name="age" value="3"></property>
</bean> 
<bean id="dog1" class="com.gvace.autowire.Dog">
 <property name="name" value="dogA"></property>
 <property name="age" value="3"></property>
</bean> 



byType

Spring look for a bean with target wiring type or its child
But only accept one bean with this type/child in the config
More than 1 bean with the same type/child to wire will cause error.

<bean id="owner" class="com.gvace.autowire.Owner" autowire="byType">
 <property name="name" value="ownerA"></property>
</bean>
<bean id="dog" class="com.gvace.autowire.Dog">
 <property name="name" value="dogB"></property>
 <property name="age" value="3"></property>
</bean> 
<!-- byType does not allow more than 1 bean with the same type to wire
<bean id="dog1" class="com.gvace.autowire.Dog">
 <property name="name" value="dogA"></property>
 <property name="age" value="100"></property>
</bean>
-->



constructor

If Spring found there is a constructor with the property/properties
And each parameter of the constructor has a bean to map by same property type
It will pick the constructor.
The picking rule is look for the constructor with the most parameters.

Will cause error if did not found or found more than 1 bean with the same type

example:

Add a constructor to Owner

 
 public Owner(Dog dog) {
  super();
  this.dog = dog;
 }



<bean id="owner" class="com.gvace.autowire.Owner" autowire="constructor">
 <property name="name" value="ownerA"></property>
</bean>
<bean id="dog" class="com.gvace.autowire.Dog">
 <property name="name" value="dogB"></property>
 <property name="age" value="3"></property>
</bean> 



autodetect

choose one between byName, byType, and constructor

Look sequence:

constructor > byType > byName



default

Follow the config of its parent: <beans default-autowire="byName">
If <beans default-autowire="no"> is not set, it's the same as <beans default-autowire="no">



Attributes

1. primary: Default: primary="true", If only one is set to primary="true", use this as wire property
So normally we do primary="false" to those are not first choice.

2. autowire-candidate="false": never see this bean as auto-wire choice.








Spring Bean config/ Dependency Injection

XML

BeanFactory/ApplicationContext
  1. XmlBeanFactory
  2. ClassPathXmlApplicationContext
  3. XmlWebApplicationContext

Lazy mode

Spring default is not lazy mode, when spring starts up, it inits all beans.

If we want bean to init when calling ac.getBean()
do this:
<beans .... default-lazy-init="true">


Bean Scope

<bean scope="singleton">

singleton: return the same instance when getBean(default)
prototype: create new instance everytime when getBean
request: HTTP request life cycle
session: HTTP Session life cycle
global session: Global HTTP Session life cycle, spring portlet context

Try best to avoid scope "prototype", which is heavy memory usage and mostly unnecessary

Set property with another bean

Use <ref>
<property name="emp">
 <ref bean="beanId" />
</property>


Property Injection with Collections/Array

map
set
list
collection
int[]

Array/List/Set values are primitive types

<bean id="department" class="com.gvace.collection.Department">
 <property name="name" value="Business"></property>
 <property name="empName">
  <list>
   <value>aaa</value>
   <value>bbb</value>
   <value>ccc</value>
  </list>
 </property>
</bean>


Array/List/Set values are objects
Use ref to link the instance of other beans
<bean id="department" class="com.gvace.collection.Department">
 <property name="name" value="Business"></property>
 <property name="employee">
  <set>
   <ref bean="emp1"/>
   <ref bean="emp2"/>
  </set>
 </property>
</bean>
<bean id="emp1" class="com.gvace.collection.Employee">
 <property name="name" value="empA" />
</bean>
<bean id="emp2" class="com.gvace.collection.Employee">
 <property name="name" value="empB" />
</bean>


Map property injection config
Use the following properties to build <entry>
key
key-ref
value
value-ref


<bean id="department" class="com.gvace.collection.Department">
 <property name="name" value="Business"></property>
 <property name="employeeMap">
  <map>
   <entry key="1" value-ref="emp1"/>
   <entry key="2" value-ref="emp2"/>
</map>
 </property>
</bean>
<bean id="emp1" class="com.gvace.collection.Employee">
 <property name="name" value="empA" />
</bean>
<bean id="emp2" class="com.gvace.collection.Employee">
 <property name="name" value="empB" />
</bean>


Internal Bean
<bean id="department" class="com.gvace.Department">
  <property name="Manager">
    <bean class="com.gvace.Manager">
      <property name="name" value="managerA"/>
    </bean>
  </property>
</bean>


Inherit

<!-- Graduate extends Student -->
<bean id="student" class="com.gvace.impl.Student">
 <property name="name" value="studentA" />
 <property name="age" value="15" />
</bean>
<!-- use "parent" to set the properties from extending bean -->
<bean id="graduate" parent="student" class="com.gvace.impl.Graduate">
 <property name="degree" value="Master" />
</bean>



java.util.Properties

Properties implements Map
So we can load the Properties like the following

<bean id="department" class="com.gvace.impl.Department">
  <property name="pp">
    <props>
      <prop key="pp1">aaa</prop>
      <prop key="pp2">bbb</prop>
    </props>
  </property>
</bean>


NULL value

<property name="value">
  <null/>
</property>



Set properties by constructor

<bean id="employee" class="com.gvace.impl.Employee">
 <constructor-arg index="0" type="java.lang.String" value="empA"/>
 <constructor-arg index="1" type="int" value="15"/>
</bean>







Spring Bean Life cycle

Life cycle of an instance from a bean

By ApplicationContext


  1. Create an instance
  2. Set property of the instance
  3. *BeanNameAware(Interface) implement to call setBeanName, pass you BeanName
  4. *BeanFactoryAware(Interface) implement to  call setBeanFactory, pass you BeanFactory
  5. *ApplicationContextAware(Interface) implement to  call, pass you ApplicationContext
  6. *BeanPostProcessor(Interface) postProcessBeforeInitialization(function), any one or more Bean class to implement to call, like filter, remember to return the object. AOP
  7. *InitializingBean(Interface) implement to call afterPropertiesSet
  8. *customized function defined by "init-method" in <bean> config, or @PostConstruct
  9. *BeanPostProcessor(Interface) postProcessAfterInitialization(function)
  10. Instance Ready to use
  11. Spring Container closing
  12. *DisposableBean(Interface) implement to call destroy
  13. *customized function defined by "destroy-method" in <bean> config, or @PreDestroy

Most common steps: 1,2,6, 9,10,11

* steps: optional
Suggested to use customized function since it's not bonded to Spring

By BeanFactory

Do NOT have ApplicationContext and BeanPostProcessor
Only have 1,2,3,4,7,8,10,11,12,13





Wednesday, March 23, 2016

Spring

Container Framework, to config bean and maintain relationship between beans

Bean:

javabean
service
action
data source
dao
ioc(inverse of control)
di(dependency injection)



http://maven.springframework.org/release/org/springframework/spring/

Require jar:
spring jar
common.logging.jar

ioc
Inverse of Control: 
Move the control of beans creation, and relationship maintenance from your code to Spring.
So do not need to maintain code, just maintain applicationContext config. This is mainly done by DI in spring.


DI
Dependency Injection





applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 
 <bean>: 
 when spring framework loads
 spring will auto create a bean instance and put it into memory
-->
<!--
 equivalent to: 
 UserService userService = new UserService();
 userService.setName("abc");
-->
<bean id="userService" class="com.service.UserService">
 <property name="name">
  <value>abc</value>
 </property>
 <!-- 
  ref is to another bean's if, used when the property is also a bean  
  -->
 <property name="bybService" ref="bybService"></property>
</bean>
<bean id="bybService" class="com.service.BybService">
 <property name="name">
  <value>fff</value>
 </property>
</bean>
</beans>

Get a ApplicationContext

  1. ClassPathXmlApplicationContext: by class path
  2. FileSystemXmlApplicationContext: by directory path
  3. XmlWebApplicationContext: for web application to load


Get a Bean from ApplicationContext(Immediately):

//Init all beans, create instances for all singleton beans immediately
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

//Two ways
//class path directory
ApplicationContext ac0 = new ClassPathXmlApplicationContext("com/gvace/impl/beans.xml");

//file system directory
ApplicationContext ac1 = new FileSystemXmlApplicationContext("src/com/gvace/impl/beans.xml"); 

//get configs from multiple files
String[] configLocations = new String[]{"applicationContext.xml","applicationContext-editor.xml"};
ApplicationContext ac2 = new ClassPathXmlApplicationContext(configLocations);
UserService userService = (UserService)ac.getBean("userService");
//get configs by pattern
ac = new ClassPathXmlApplicationContext("applicationContext*.xml");
//get bean by id





Get a Bean from Bean Factory(Delay):

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); 
//Init the bean, but not creating instances

factory.getBean("userService");
//create an instance


Scope

singleton: initialized instance when bean creates by application context
prototype: one bean to many instances
request: get a new instance for a bean in each request
session: get a new instance for a bean in each session
global session: get a new instance for a bean in whole spring container




Sunday, March 20, 2016

Hibernate Cache

Session Cache(1st Level Cache)

1st Level Cache will be pushed during the following functions:
save, update, saveOrUpdate, load, get, list, iterate, lock

1st Level Cache will be loaded during the following functions:
get, load


1st Level Cache cleanning
default enabled, will not auto clean, so do cleaning manually

Example:
session.evict(student); //remove this instance from 1st level cache
session.clear(); //completely clear all instances from the session

Cache Life cycle

All instances will be purged when session closed.


SessionFactory Cache(2st Level Cache)


Stay with SessionFactory, so it's longer than 1st Level.

Has different third-party implementations.

Cache name
Cache Type Provider class
Hashtable
Memory Org.hibernate.cache.HashtableCacheProvider
EHCache
Memory, hard drive Org.hibernate.cache.EhCacheProvider
OSCache(out of maintain)
Memory, hard drive Org.hibernate.cache.OSCacheProvider
SwarmCache
distributed
(no distributed transaction)
Org.hibernate.cache.SwarmCacheProvider
JBoss Cache 1.x
distributed
(distributed transaction)
Org.hibernate.cache.TreeCacheProvider
JBoss Cache 2
distributed
(distributed transaction)
Org.hibernate.cache.JBossCacheRegionFactory


Four usage
1. Use in hibernate.cfg.xml: <class-cache usage="read-write">
2. Use in each *.hbm.xml <cache usage="read-write">

read-only
read-write
nonstrict-read-write
transactional


EHCache Example

hibernate.cfg.xml
  
  <property name="hibernate.generate_statistics">true</property>
  <property name="hibernate.cache.use_structured_entries">true</property>
  <property name="hibernate.cache.use_second_level_cache">true</property>
  <property name="hibernate.cache.use_query_cache">true</property>
  <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
  
  <mapping resource="com/gvace/notebook/domain/User.hbm.xml"/>
  <mapping resource="com/gvace/notebook/domain/Message.hbm.xml"/>
  
  <class-cache usage="read-write" class="com.gvace.notebook.domain.User"/>
  <class-cache usage="read-write" class="com.gvace.notebook.domain.Message"/>
-----------------------------------------------------

ehcache.xml

Optional, customize configs for each model/POJO/domain


2nd Level Cache Statistics

To generate statistics of cache for 2nd Level Cache
  <property name="hibernate.generate_statistics">true</property>

Get statics like follows:

SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
System.out.println("AAa"+sessionFactory.getStatistics());

Useful statistics

second level cache puts=10
second level cache hits=0
second level cache misses=0







Friday, March 18, 2016

Hibernate Lazy

Lazy: load on demand

Return proxy instead of target object, so load query when you call get functions.

Proxy example:

One-to-one object: HibernateProxy
Set: PersistentSet

So object MUST NOT set as final.


Hibernate default is lazy="true", this will cause error when you use related object when session is already closed.
If set a lot lazy="false", a lot unnecessary query will run, which cause a waste.

Solutions:
  1. Hibernate.initialize
  2. config in hbm.xml, lazy=false
  3. Web filter, openSessionInView
openSessionInView is better than others, since you don't know if you really loading related object or not. All we do just extend life cycle of session.

1. call getXX() function during the session

2. Hibernate.initialize during the session.


Hibernate.initialize(xxx);
//xxx is the property: obj.getXXX()


3. Config hbm.xml

In many-to-one(many side), if set the class to lazy="false"
Hibernate will use left outer join to load related data with the original data in one time.

In one-to-many(one side), if set the set to lazy="false"
Hibernate will first load the object list, then load ALL related objects from separate query for each object.




4. openSessionInView
Set lazy="true"(or just do not set lazy mode)
Make the query session alive, starts from the web filter, until jump out from the web filter.
All hibernate usage then REQUIRED to use getCurrentSession!
And also DONOT close session other than in this filter
This will make session stay open for longer time.

Filter:
for Spring, use Spring provided OpenSessionInViewFilter:

 <!-- OpenSessionInView with spring filter -->
 <filter>
  <filter-name>openSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>openSessionInViewFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


Or make filter your self:

public class HibernateSessionFilter extends HttpServlet implements Filter {

 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  Session session = null;
  Transaction tx = null;
  try {
   session = HibernateUtil.getCurrentSession();
   tx = session.beginTransaction();
   chain.doFilter(request, response);
   tx.commit();
  } catch (Exception e) {
   if(tx!=null)tx.rollback();
   throw new RuntimeException(e.getMessage());
  } finally {
   HibernateUtil.closeCurrentSession();
  }

 }

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {

 }

}



Issues for 1 and 2
hard to know when to pre-load, and when to not-pre-load.
If set to pre-load: may waste unnecessary querys
If set to not-pre-load: will cause error when getting related property


Scan device in network, find IP/ports

ip addr

sudo arp-scan --interface wlp2s0 192.168.68.0/23

sudo arp-scan --interface wlp2s0 192.168.68.0/23|grep -i '00:0e'


Scan open ports of ip

nmap 192.168.69.91 -p 1-65535

Wednesday, March 9, 2016

Hibernate Cascade

Transitive Persistence

Normally used to <one-to-many> and <one-to-one>: "one" side
Not suggest for <many-to-one> and <many-to-many>: "many" side


  1. Can used in <Set> and also <Property>
  2. Used in <one-to-many>, "one" side
  3. Used in <one-to-one>, primary object side
Cascade options:

none
all
save-update: 
delete
lock
refresh
evict
replicate
persist
merge
delete-orphan(one-to-many)


Examples
cascade="all"
cascade="persist,merge,save-update"
cascade="delete"

Example:(one-to-many)

Auto delete students when delete a department.

in Department.hbm.xml
<set name="students" cascade="delete">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

when doing delete a department, all students in its <set> will be deleted


Example:(one-to-many)

Auto add/update students when save a department.

in Department.hbm.xml
<set name="students" cascade="save-update">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

When save a department, all students in its <set> will be saved/updated


Example:(many-to-one)

Auto add/update department when save a student

in Student.hbm.xml
<many-to-one name="department" column="dept_id" cascade="save-update">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

When saving/updating a student, its department will also be saved/updated







Sunday, March 6, 2016

Hibernate Object Relationships

one-to-one

1: based on Primary key one-to-one

Two tables, A and B.
B's foreign id is A's id.

Student obj: {id,name,idCard}

<one-to-one name="idCard"/>


IdCard obj: {id,expdate,student}

Generate primary id by a foreign key

<!-- set id as foreign key -->
<id name="id">
  <generator class="foreign">
  <param name="property">student</param>
  </generator>
</id>
<one-to-one name="student" constrained="true">

In <one-to-one>
constriained="true": copy target id as self id, and make as foreign key relationship in table
constriained="false": simply copy target id as self id


2: based on Foreign key one-to-one

To make a one-to-one relationship based on Foreign key:
simply use <many-to-one> and set unique="true"

In IdCard.hbm.xml

<many-to-one name="student" unique="true" />




many-to-one

Student to Department

<hibernate-mapping package="com.gvace.domain">
 <class name="Student">
  <id name="id" type="java.lang.Integer">
   <generator class="increment"></generator>
  </id>
  <property name="name" type="java.lang.String">
   <column name="name" length="64" not-null="true"/>
  </property>
        <many-to-one name="department" column="dept_id" />
        <!-- 
         "name": property name
         "column": column name in this table
          -->
 </class>
</hibernate-mapping>


Issue: in lazy mode, after session closed, the foreign property still not load.
Solution:

  1. Hibernate.initialize(student.getDepartment()); //initialize proxy
  2. <class name="Department" lazy="false"> //disable lazy mode
  3. Filter(web project): openinSessionInView

one-to-many

Get all students from a department

private Set students = new HashSet(0); //can be any collection

In hbm.xml, use <set> to represent one-to-many property

<hibernate-mapping package="com.gvace.domain">
 <class name="Department" lazy="false">
  <id name="id" type="java.lang.Integer">
   <generator class="increment"></generator>
  </id>
  <property name="name" type="java.lang.String">
   <column name="name" length="64" not-null="true"/>
  </property>
  <!-- One to Many -->
  <set name="students" >
   <key column="dept_id"></key>
   <one-to-many class="Student"/>
  </set>
 </class>
</hibernate-mapping>


cascade="save-update"
In <set>: If we want automatically save each record in <set> property, use cascade="save-update"


many-to-many


Normally we CONVERT many-to-many relationship to two one-to-many, and one many-to-one
We create a new table for only relationship mapping


Student obj: {id, name, Set<StudentCourse> studentCourses}
Course obj: {id, name,  Set<StudentCourse> studentCourses}
StudentCourse obj: {id, Student, Course, grade}

Target Student table: {id, name}
Target Course table: {id, name}
Target StudentCourse table: {id, student_id, course_id, grade}

Student.hbm.xml

<set name="studentCourses">
  <key column="student_id" />
  <one-to-many class="StudentCourse" />
</set>

Course.hbm.xml

<set name="studentCourses">
  <key column="course_id" />
  <one-to-many class="StudentCourse" />
</set>


StudentCourse.hbm.xml

<many-to-one name="course" column="course_id" />
<many-to-one name="student" column="student_id" />




Hibernate Domain/Model/POJO



  1. Default constructor
  2. Has an id(primary key) for identity only, no content meaning for this id
  3. getter/setter

Session methods


  • close()
  • clear(): Completely clear the session
  • connection(): get JDBC connection
  • delete(Object object): Remove a persistent instance from the database
  • evict(Object object): Remove instance from the session cache
  • flush(): force session to flush



Transient state
Object does NOT match any data in the db table
NO session is related to this object
If exceed scope, JVM will do garbage collection.

Normally to be the object has been created but not related to any session nor db record.

Persistent state
Object has matched data in the db table
Object also related to a session
Session is not closed
Transaction is not committed.

If persistent state object changes, the db record will be changed when transaction commited.

employee.setName("abc");
transaction.commit();
//do update db immediately


Detached state
Object has matched data in the db table
Object is NOT related to any session

If detached state object changes, hibernate will not notice that, and db will not change








Thursday, March 3, 2016

HQL and Criteria

HQL: Hibernate Query Language

HQL:

  • Case sensitive for Java class and field
  • HQL query is to object, not table
  • support polymorphism
Query q = session.createQuery(hql);


  • from Person
  • from User user where user.name=:name
  • from User user where user.name=name and user.birthday <:birthday
Table primary key: better not to be business logic


Generating domain file and *.hbm.xml file: if we have primary key and foreign key, first generate for primary table, then generate foreign table

session.delete
session.save
session.persist
session.update
session.load
session.get

Examples


1. select all field from table
The result can be as List<Student>
//hql: get all field from table

List<Student> list1 = session.createQuery("from Student where id<10").list();
//"Student" is class name, not table name
//"from Student" default as "select *"

2. select part of fields from table(more than one column)
The result can NOT be List<Student>, it is List<Object[]>
 //hql: get part of fields from table
 List<Object[]> list1 = session.createQuery("select name,department from Student").list();
 //"Student" is class name
 //only returns List<Object[]>
//Also can do query like distinct, between and, in(), count,avg, having,max,min,sum etc..
List<Object[]> list2 = session.createQuery("select distinct age,gender from Student where age between 10 and 30").list();

like
List<Object[]> list3 = session.createQuery("from Student where name like '%Cat%'").list();


from Student where name like "%Cat%"

3. select only one column from table
The result is List<Object>, NOT List<Object[]>


4. Foreign key: foreign key is already transformed to class on the field, so calling id name directly in hql will cause exception, we have to check class field to match hql columns

List<Object[]> list1 = session.createQuery("select id,course.id,grade from Stucourse").list();

5. uniqueResult(): select unique record from table
Must make sure it has only one or no record
returns null if no record
Throws exception if multiple record found, so setMaxResults(1) can make sure it has only one record
Student s = (Student)session.createQuery("from Student where id<10").setMaxResults(1).uniqueResult();

6. setFirstResult(int): starting record from query, default start from 0

7. setMaxResults(int): retrieve only certain amount of records or less
Pagination will be used by setFirstResult(int) and setMaxResults(int)


8. Parameters in Query
Two styles

  • "?", starts from 0
    Query query = session.createQuery("from Student where department=? and age>?");query.setString(0, "计算机系");
    query.setInteger(1, 20);
    List<Student> list1 = query.list();
  • ":"
    Query query = session.createQuery("from Student where department=:dept and age>:age"); query.setString("dept", "计算机系");
    query.setInteger("age", 20);
    List<Student> list1 = query.list();


Criteria

Criteria cri = session.createCriteria(Student.class);
cri.add(Restrictions.gt("age", 10));