20 Aralık 2018 Perşembe

Session Arayüzü

Giriş
Şu satırı dahil ederiz.
import org.hibernate.Session;
Bu sınıf JPA EntityManager arayüzünden kalıttığı için JPA metodları rahatlıkla kullanılabilir. Generic kodlarda kullanmak için bir örnek burada

Session Ne İşe Yarar?
Açıklaması şöyle.
A session in Hibernate is an object that communicates with the database.
1. Each session has its own database connection;
2 .A session is created by the "openSession()" method of the SessionFactory object;
3. Creating a session object is a light-weight process;
4. A session should be closed whenever the database operation is completed to release the database connection;
5. A session object is not thread-safe.
Batch işler için Hibernate StatelessSession arayüzü daha iyi.

Cluster
Şu soru ilginç.
Let's say we have multi-clustered application servers, where each has created its own SessionFactory (pointing to same single DB). One server retrieves a record [Person with ID = 1] which caches the same in the session (s1), which is still open.
In the meantime, another server, opens another session (s2) and updates the Person record with ID = 1. Now what happens to the Person record cached within s1? Will it be a stale record?
constructor
Bu nesne Hibernate SessionFactory tarafından yaratılır. Şöyle yaparız.
SessionFactory sessionFactory = ...;
//auto close session after try block
try (Session session = sessionFactory.openSession()) {
  ...
}
catch (Exception e) {
  ...
}
beginTransaction metodu
Şöyle yaparız.
Session session = ...;
Transaction t = session.beginTransaction();

Employee e1=new Employee();
e1.setId(1001);
e1.setFirstName("sonoo");
e1.setLastName("jaiswal");

Employee e2=new Employee();
e2.setId(1002);
e2.setFirstName("vimal");
e2.setLastName("jaiswal");

session.persist(e1);
session.persist(e2);

t.commit();
session.close();
byNaturalId metodu
NaturalIdLoadAccess nesnesi döner. Şöyle yaparız.
public AddressKeyEntity getAddressKeyEntity(AddressKeyEntity addressKey) {
  AddressKeyEntity item = session.byNaturalId(AddressKeyEntity.class)
    .using("address", addressKey.getAddress())
    .using("city", addressKey.getCity())
    .using("state", addressKey.getState())
    .using("zip", addressKey.getZip())
    .with(LockOptions.UPGRADE.setTimeOut(LockOptions.WAIT_FOREVER))
    .load();
  if(item != null) {
    return item;
  } else {
    sessionFactory.getCurrentSession().persist(addressKey);
    return addressKey;
  }
}
clear metodu
Açıklaması şöyle.
When this method called, the first-level cache for that session is cleared, as well as all the objects from the cache.

close metodu
Örnek
Şöyle yaparız.
session.close();
Örnek
Şöyle yaparız.
@Override
public void save(Book book) {
  Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();
  try {
    session.save(book);
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
    try {
      tx.commit();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      session.close();
    }
  }
}
contains metodu
Açıklaması şöyle.
This method can be used to check that the given instance is associated with this session.
createCriteria metodu
Bu method Hibernate 5 ile deprecate edildi. JPA ile gelen getCriteriaBuilder() metodu kullanılmalı.Açıklaması şöyle.
/** @deprecated */
@Deprecated
Criteria createCriteria(Class var1);

/** @deprecated */
@Deprecated
Criteria createCriteria(Class var1, String var2);

/** @deprecated */
@Deprecated
Criteria createCriteria(String var1);

/** @deprecated */
@Deprecated
Criteria createCriteria(String var1, String var2);
Örnek
Şöyle yaparız.
Criteria criteria = session.createCriteria(Foo.class);
createNamedQuery metodu
İmzası şöyle.
@Override
public QueryImplementor createNamedQuery(String name);
Açıklaması şöyle.
The JPA-defined named query creation method. This form can represent an HQL/JPQL query or a native query.
Parameters:
name the name of a pre-defined, named query
getNamedQuery() ile aynı işi yapar.

createQuery metodu
Hibernate Query nesnesi yaratır. HQL cümlesi çalıştırmamızı sağlar.
Örnek
Şöyle yaparız.
Query query = session.createQuery("from Company");
Örnek
Şöyle yaparız.
@Autowired
SessionFactory sessionFactory;

public List<MyEntity> findSomeApples() {
  Session session = sessionFactory.getCurrentSession();
  List<?> result = session.createQuery("from MyEntity where apples=7")
      .list();
  @SuppressWarnings("unchecked")
  List<MyEntity> resultCasted = (List<MyEntity>) result;
  return resultCasted;
}
createSqlQuery metodu
Hibernate SQLQuery nesnesi döndürür. Native SQL cümlesi çalıştırmamızı sağlar. Şöyle yaparız.
StringBuilder query = new StringBuilder("SELECT x, y, z FROM ...");

SQLQuery query = session.createSQLQuery(query);
List result = query.list();
delete metodu
Eğer silinecek nesne elimizde var ise şöyle yaparız.
@Transactional    
public void deleteUser(User user) {
    sessionFactory.getCurrentSession().delete(user);
}
Sadece primary key var ise şöyle yaparız.
@Transactional
public void deleteOrg(int userId) {
  User user = sessionFactory.getCurrentSession().get(User.class, userId);
  sessionFactory.getCurrentSession().delete(user);
}
HQL ile silmek istersek şöyle yaparız.
@Transactional
public void deleteUser(int userId) {
  Query q = session.createQuery("delete User where id = :userId");
  query.setParameter("userId", userId);
  q.executeUpdate();
}
evict metodu
Açıklaması şöyle.
It removes an object from the session cache. After removing the object from the session, any change to object will not be persisted.

get metodu
Nesnenin kendisini yükler. Şöyle yaparız
@Transactional
public void deleteOrg(int userId) {
  User user = sessionFactory.getCurrentSession().get(User.class, userId);
  ...
}
getCriteriaBuilder metodu
Şöyle yaparız
javax.persistence.criteria.CriteriaBuilder
javax.persistence.criteria.CriteriaQuery

// Create CriteriaBuilder
CriteriaBuilder builder = session.getCriteriaBuilder();

// Create CriteriaQuery
CriteriaQuery<YourClass> criteria = builder.createQuery(YourClass.class);
getIdentifier metodu
Şöyle yaparız.
Serializable id = session.getIdentifier(myEntity);
Eğer JPA 2 kullanıyorsak şöyle yaparız.
em.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(myEntity);
getNamedNativeQuery metodu
Örnek
hbm.xml dosyasında şöyle bir kod olsun.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  ...
  <sql-query callable="true" name="GetWebUserData" read-only="false">
    <return alias="gwud" class="com.WebUserData">
      <return-property column="KEYID" name="keyId" />
      <return-property column="NAME" name="name" />
    </return>
    <query-param name="requestId" type="java.lang.long" />
    <![CDATA[CALL GetWebUserData(:requestId)]]>
  </sql-query>
</hibernate-mapping>
Şöyle yaparız.
public List<?> callStoredProc() {
  try {
    Session session = sessionFactory.openSession();
    Transaction txD = session.beginTransaction();
    NativeQuery<?> nativeQuery = session.getNamedNativeQuery("GetWebUserData");
    nativeQuery.setParameter("requestId", "1");
    nativeQuery.setReadOnly(false);

    List<?> rows = nativeQuery.list();

    txD.commit();
    session.close();

    return rows;
  } catch (Exception e) {
    e.printStackTrace();
    return null;
  }
}
getNamedQuery metodu
İmzası şöyle.
public QueryImplementor getNamedQuery(String name);
Açıklaması şöyle.
Create a Query instance for the named query.
Parameters:
queryName the name of a pre-defined, named query
createNamedQuery() ile aynı işi yapar. NamedQuery Entity nesnesine yazılır.

Örnek
Elimizde bir NamedQuery olsun.
@Entity
@NamedQueries({
  @NamedQuery(
    name = "get_technicans",
    //counting minimal distance and sorting by ascending
    query = "FROM Technician t WHERE t.keywords LIKE :name " +
            "ORDER BY (t.longitude-:longitudeUser) + (t.latitude-:latitudeUser)"
    )
})
@Table(name = "technicians")
public class Technician {

  @Column(name = "keywords")
  private String keywords;

  @Column(name = "longitude")
  private Double longitude;

  @Column(name = "latitude")
  private Double latitude;

  public Technician() {}

  ...
}
Şöyle yaparız.
//auto close session after try block
try (Session session = sessionFactory.openSession()) {
  Double myLongitude = 123456.123456d;
  Double myLatitude = 654321.654321d;
  String name = "plumber";

  //and you get your list
  List<Technician> technicansList = (List<Technician>)
  session.getNamedQuery("get_technicans")
                    .setString("name", name)
                    .setDouble("longitudeUser", myLongitude)
                    .setDouble("latitudeUser", myLatitude)
                    .list();
}
getTransaction metodu
beginTransaction ile başlatılan etkin Transaction nesnesini döndürür. Şöyle yaparız.
Session session = ...;
try {
  session.beginTransaction();
  ...
  session.getTransaction().commit();
} catch (Exception e) {
  session.getTransaction().rollback();
  ...  
}
load metodu - Class + id
Nesnenin kendisi yeriner proxy nesnesi yükler.
Örnek
Elimizde şöyle bir sınıf olsun
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Entity
@Table(name = "person")
public class Person {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private int id;
...
}
Bu sınıfı şöyle yükleriz.
int id = 10;   
Person per = session.load(Person .class, id);
load metoud - Class + id + LockMode
İmzası şöyle
Query.lockMode (Class theClasa, Serializable id, LockMode lockMode);
merge metodu
Örnek ver

saveOrUpdate metodu
Açıklaması şöyle
saveOrUpdate() is good for instances (with or without an @Id value) that are known to the session already.
Paramtere olarak verilen nesenin session içinde olması gerekir. Şu kod exceptiın fırlatır.
Foo foo = new Foo();
foo.setGuid(other.getId());
foo.setName(other.getName());
...
session.saveOrUpdate(foo);

update metodu
Örnek ver

save metodu
Örnek ver