一。简述
1.优点:
Hibernate的好处:拥有通用的数据库操作方法,除特殊查询外不用手动去写SQL
2.通用DAO的封装,由于通用性考虑所以所有返回值在使用前需强转成所要查询的类型
package com.hibernate.dao;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import com.inventec.ps.util.CheckUtils;
/**
* The Class BasicHibernateDAO.
*
* @author yongqi_wang
*/
public abstract class AbstractHibernateDAO {
public final Logger logger = LoggerFactory.getLogger(this.getClass());
/** The session factory. */
protected SessionFactory sessionFactory;
/**
* Gets the session factory.
*
* @return the session factory
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* Sets the session factory.
*
* @param sessionFactory
* the session factory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Open session. 打开后必须主动关闭。
*
* @return the session
*/
protected Session openSession() {
return sessionFactory.openSession();
}
/**
* Current session. DAO 必须在事务(比如@Transactional)的管理内,否则得不到session。
* 创建的session会和绑定到当前线程,而openSession不会。
* 创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭。
*
* @return the session
*/
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
/**
* id查询
* @param clazz 类型.class(不得为空)
* @param id 主键id
*/
@Transactional(readOnly = false)
public Object selectObjectById(Class<?> clazz,String id){
return currentSession().get(clazz, id);
}
/**
* 添加
*/
@Transactional(readOnly = false)
public void save(Object object){
currentSession().save(object);
}
/**
* 批量添加
*/
@Transactional(readOnly = false)
public void saveAll(List<?> list){
Session session = currentSession();
for (int i = 0;i < list.size();i++) {
if(i % 500 == 0){
session.flush();
}
session.save(list.get(i));
}
session.flush();
session.clear();
}
/**
* 修改
*/
@Transactional(readOnly = false)
public void update(Object object){
currentSession().update(object);
}
/**
* 删除
*/
@Transactional(readOnly = false)
public void delete(Object object){
currentSession().delete(object);
}
/**
* 根据id删除
* @param clazz 实体类class (不得为空)
* @param id 要删除的对象id
*/
@Transactional(readOnly = false)
public void deleteObjectById(Class<?> clazz, String id) {
Session session = currentSession();
Object record = session.get(clazz, id);
if(CheckUtils.noEmpty(record)){session.delete(record);}
}
/**
* 批量删除
*/
@Transactional(readOnly = false)
public void deleteAll(List<?> list){
Session session = currentSession();
for (int i = 0;i < list.size();i++) {
if(i % 500 == 0){
session.flush();
}
session.delete(list.get(i));
}
session.flush();
session.clear();
}
/**
* 根据多个id查询
* @param clazz 对象class
* @param list id的List集合
* @return
*/
@Transactional(readOnly = false)
public List<?> selectListById(Class<?> clazz,List<String> list){
Session session = currentSession();
Criteria crit = session.createCriteria(clazz);
if(list != null && list.size() > 0){
crit.add(Restrictions.in("id", list));
}
List<?> li = crit.list();
session.flush();
session.clear();
return li;
}
/**
* 条件查询 排序条件写的比较烂,也懒的改了 有需要的朋友可以自己修改下
* @param clazz 要查询的实体类class (不得为空)
* @param map 查询条件 key:属性名 value:要查询的值
* @param map2 分页与排序条件
*/
@Transactional(readOnly = false)
public List<?> selectListByMap(Class<?> clazz,Map<String,Object> map,Map<String,Object> map2){
Session session = currentSession();
Criteria crit = session.createCriteria(clazz);
if(CheckUtils.noEmpty(map)){
crit = crit.add(Restrictions.allEq(map));
}
if (CheckUtils.noEmpty(map2.get("order"))?map2.get("order").equals("desc"):false) {
if(CheckUtils.noEmpty(map2.get("sort"))){
crit.addOrder(Order.desc(map2.get("sort").toString()));
}
} else {
if(CheckUtils.noEmpty(map2.get("sort"))){
crit.addOrder(Order.asc(map2.get("sort").toString()));
}
}
if(CheckUtils.noEmpty(map2.get("page")) && CheckUtils.noEmpty(map2.get("rows"))){
Integer rows = (Integer) (map2.get("rows"));
Integer page = (Integer) (map2.get("page"));
crit.setFirstResult(rows * (page - 1));
crit.setMaxResults(rows);
}
List<?> list = crit.list();
session.flush();
session.clear();
return list;
}
/**
* 条件查询数据条数
* @param clazz 要查询的实体类class (不得为空)
* @param map 查询条件
*/
@Transactional(readOnly = false)
public Integer selectListByMapNumber(Class<?> clazz,Map<String,Object> map){
Session session = currentSession();
Criteria crit = session.createCriteria(clazz);
if(CheckUtils.noEmpty(map)){
crit = crit.add(Restrictions.allEq(map));
}
return ((Number) crit.setProjection(Projections.rowCount()).uniqueResult()).intValue();
}
}3.hibernate自定义sql
此方法不建议经常使用,因为这样会造成大量的sql语法写入service中,与MVC的理念偏离,如有必要建议在dao中使用StringBuffer将所有sql进行书写,虽然会造成代码冗余但会使代码可读性提高
/**
* 测试用例
* 注意:
* ① 根据hibernate hql语句的生成特性,会将所有的查询条件封装成map
* 所以如果使用map来作为方法的参数来达到通用性的目的,提交返回值前
* 要将此map关闭,否则map会在hql语句生成时被一起传递到hql语句中
* 导致查询失败抛出异常
* ② 查询后要清空session缓存,防止脏数据产生
* ③ 自定义sql书写时需注意sql语法,建议先使用Navict或其他工具验证sql后再书写
* ④ sql中有字符串作为判断条件时使用单引号将参数括起,具体书写与sql语法一致在使用时注意标点符号
* @param clazz 要查询的对象class
* @param map 由于自定义sql无法达成与实体类映射关系,所以需要手动做ORM
* 1.要查询的数据库中的 字段名 as 实体类名
* 2.要查询的数据库表名
*
* @return
*/
@SuppressWarnings("unchecked")
public List<?> queryUaMaterialhistoryByMap(Class<?> clazz,Map<String, Object> map) {
Session session = currentSession();
StringBuffer sb = new StringBuffer();
sb.append("select ");
sb.append(map.get("select"));
sb.append(" from ");
sb.append(map.get("from"));
if(CheckUtils.noEmpty(map.get("where")){
sb.append(" where ");
sb.append(map.get("where"));
}
if (CheckUtils.noEmpty(map.get("order")) ? map.get("order").equals("desc") : false) {
sb.append(" order by ");
sb.append(map.get("sort"));
sb.append(" desc ");
} else {
sb.append(" order by ");
sb.append(map.get("sort"));
sb.append(" asc ");
}
Query query = session.createSQLQuery(sb.toString());
if (CheckUtils.noEmpty(map.get("page")) && CheckUtils.noEmpty(map.get("rows"))) {
Integer rows = (Integer) (map.get("rows"));
Integer page = (Integer) (map.get("page"));
query.setFirstResult(rows * (page - 1));
query.setMaxResults(rows);
}
map.clear();
List<?> list = query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
session.flush();
session.clear();
return list;
}4.session中createSQLQuery和createQuery方法的区别 ① createQuery 所有查询条件使用实体类中的属性名
② createSQLQuery 放弃hibernate的关系映射操作,自己手动通过字段别名映射实体
③ 使用createQuery可以不写select语句直接从from语句开始书写
例:
Query query = session.createQuery("from TestUser");
List<User> list = query.list();5.openSession与currentSession的区别
① 功能:
openSession每一次调用都会产生一个新的session
currentSession 一个线程获得的session是同一个
② 使用:
(1)currentSession必须在hibernate.cfg.xml中进行额外的配置
(2)currentSession获得的Session对象必须运行在事务中
(3)currentSession所获得的Session对象在事务结束后会自动关闭
(4)currentSession进行Session的线程绑定,可以进行事务控制
12万+

被折叠的 条评论
为什么被折叠?



