这里写目录标题
主流的orm框架之一、与mybatis框架类似,java web开发常用的框架
本文参考3W学习方法来叙述内容。
一、What
1、什么是Hibernate?
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架。
–引用自百度百科
二、Why
1、Hibernate的特点?
- 将对数据库的操作转换为对Java对象的操作,从而简化开发。通过修改一个“持久化”对象的属性从而修改数据库表中对应的记录数据。
- 有丰富的映射方式将Java对象之间的关系转换为数据库表之间的关系。
- 屏蔽不同数据库实现之间的差异。在Hibernate中只需要通过“方言”的形式指定当前使用的数据库,就可以根据底层数据库的实际情况生成适合的SQL语句。
三、How
1、怎样掌握Hibernate?
1.1、了解六个API
- Session
- 执行被持久化对象的CRUD操作
- 非线程安全
- SessionFactory
- 数据存储源的代理,创建Session对象
- 每个数据库指定一个SessionFactory
- Transaction
- 统一事务的操作
- Query
- 对持久对象进行查询(HQL语言或本地数据库的SQL语句)
- Criteria
- 与Query接口非常类似,执行面向对象的标准化查询
- Configuration
- 对Hibernate 进行配置
- 首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。
1.2、使用步骤
1.2.1、获取SessionFactory的实例对象
主要两种方式:
- 通过Configuration对象构建,前提是创建了hibernate.cfg.xml配置文件(默认放在src根目录下)
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
// 指定配置文件路径
SessionFactory sessionFactory = new Configuration().configure("classpath:hibernate.cfg.xml").buildSessionFactory();
- spring自动注入方式,spring的xml配置文件中声明sessionFactory的bean
<!-- dataSource DruidDataSource对应更换为使用的数据源类-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${druid.pool.maxActive}"/>
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="120000" />
<property name="validationQuery" value="SELECT 1" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<property name="keepAlive" value="true" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" destroy-method="destroy">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.breaker.jst"/>
<!-- <property name="configLocation" value="classpath:hibernate.cfg.xml"/> -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<!-- Hibernate Search index directory -->
<prop key="hibernate.search.default.indexBase">target/index</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
</bean>
// 自动注入SessionFactory
@Autowired
private SessionFactory sessionFactory;
1.2.2、获取Session的实例对象
sessionFactory.getCurrentSession();
// 当需要打开多个session时、采用openSession方法
sessionFactory.openSession();
1.2.3、操作数据库
主要有三种方式:
HQL方式
HQL没有表和字段的概念,只有类、对象和属性的概念,即只操作java对象就相当于操作表。
注意:表名大小写不敏感,对象名大小写敏感
(1) 以"?"作为占位符,按索引入参
// from后的"User"为java类名,sql中对应的才是表名
String hql = "from User where id = ? ";
Query query = session.createQuery(hql);
// 索引从0开始
query.setInteger(0,666);
Object obj = query.uniqueResult();
User user = (User) obj ;
session.close();
(2)以变量名称作为占位符,按名称入参
// from后的"User"为java类名,sql中对应的才是表名
String hql = "from User where id = :uid ";
Query query = session.createQuery(hql);
query.setInteger("uid",666);
Object obj = query.uniqueResult();
User user = (User) obj ;
session.close();
Criteria方式
Criteria是一种比HQL更面向对象的查询方式。
(1)旧方式(5.2版本后不推荐)
Criteria criteria = session.createCriteria(Cat.class);
criteria.add(Restrictions.eq("name", "tom"));
List<Cat> list = criteria.list();
(2)5.2版本后推荐方式
// Create CriteriaBuilder
CriteriaBuilder builder = session.getCriteriaBuilder();
// Create CriteriaQuery
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);
// 设置where条件
criteria.where(builder.like(root.get("loginName"), "%i%"));
// 创建query 查询
Query<User> query = session.createQuery(criteria);
// 返回结果
List<User> list = query.list();
原生SQL
违背了hibernate的跨平台特点,不宜维护,不面向对象,不推荐使用。
String sql = "select * from user where id = :uid";
NativeQuery query = session.createNativeQuery(sql);
query.setParameter("uid", 5);
List<Object[]> list = query.list();
List<User> userList = new ArrayList();
for(Object[] objs : list) {
User user = new User();
user.setId(objs[0].toString());
user.setUsername(objs[1].toString());
userList.add(user);
}
session.close();
2、常见使用场景
2.1、HQL 设置参数
// from后的"User"为java类名,sql中对应的才是表名
String hql = "from User where id = :uid ";
Query query = session.createQuery(hql);
query.setInteger("uid",666);
Object obj = query.uniqueResult();
User user = (User) obj ;
session.close();
// from后的"User"为java类名,sql中对应的才是表名
String hql = "from User where id = ?";
Query query = session.createQuery(hql);
query.setParameter(0,666);
Object obj = query.uniqueResult();
User user = (User) obj ;
session.close();
2.2、Criteria 多条件查询、排序、分页
// 上文获取session实例
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);
List<Predicate> predicateList = new ArrayList<>();
List<Order> orderList = new ArrayList<>();
predicateList.add(builder.equal(root.get("id"), 123);
predicateList.add(builder.like(root.get("name"), "zhangs"));
orderList.add(builder.desc(root.get("name")));
orderList.add(builder.asc(root.get("id"))
Predicate[] predicates = predicateList.toArray(new Predicate[predicateList.size()]);
// 多个条件拼接
criteria.where(builder.and(predicates));
Order[] orders = orderList.toArray(new Order[orderList.size()]);
// 多个排序
criteria.orderBy(orders);
Query<User> query = session.createQuery(criteria);
// 分页,第1页,每页10条数据
query.setFirstResult(0);
query.setMaxResults(10);
List<User> result = query.list();
session.close();
2.3、原生SQL 多条件查询、排序、分页
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT * FROM test_user WHERE 1 ");
// listBO是查询条件的对象
if (StringUtils.isNotEmpty(listBO.getUserName())) {
sqlBuilder.append(" AND `name` LIKE '%:userName%'");
}
if (listBO.getStatus() != null) {
sqlBuilder.append(" AND status = :status");
}
if (listBO.getOrderBy() != null) {
sqlBuilder.append(" ORDER BY :orderBy :sort,id ASC ");
}
if (listBO.getOffset() != null && listBO.getLimit() != null) {
sqlBuilder.append(" LIMIT :offSet,:limit");
}
Session session = null;
try {
session = sessionFactory.openSession();
NativeQuery query = session.createNativeQuery(sqlBuilder.toString());
if (StringUtils.isNotEmpty(listBO.getUserName())) {
query.setParameter("userName", listBO.getUserName());
}
if (listBO.getStatus() != null) {
query.setParameter("status", listBO.getStatus());
}
if (listBO.getOrderBy() != null) {
query.setParameter("orderBy", listBO.getOrderBy());
query.setParameter("sort", listBO.getSort());
}
if (listBO.getOffset() != null && listBO.getLimit() != null) {
query.setParameter("offSet", listBO.getOffset());
query.setParameter("limit", listBO.getLimit());
}
query.addEntity(User.class);
return query.list();
} catch (Exception e) {
logger.error("query condition error listBO: {}", listBO);
throw e;
} finally {
if (session != null) {
session.close();
}
}
2.4、原生SQL count查询
String sql = "SELECT count(*) FROM test_user WHERE `name`=:name ";
Session session = null;
try {
session = sessionFactory.openSession();
NativeQuery query = session.createNativeQuery(sql);
query.setParameter("name", name);
return ((Number)query.uniqueResult()).intValue();
} catch (Exception e) {
throw e;
} finally {
if (session != null) {
session.close();
}
}
2.5、Criteria count查询
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
Root<User> root = criteria.from(User.class);
criteria.select(builder.count(root));
Query<Long> query = session.createQuery(criteria);
Long total = query.getSingleResult()