1. hibernate
1.0 SessionFactory、Session、openSession()、getCurrentSession()
hibernate中
-
SessionFactory 负责创建 Session,SessionFactory 是线程安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取 Session 实例,项目中只有一个sessionFactory。
-
Session是后台和数据库的一次交互,并非线程安全,所以要在当前线程中获取session。使用sf.getCurrentSession()。
-
sf.openSession();//创建新的session
-
sf.getCurrentSession();//获取当前线程的session,如果不存在,会自动创建。
- 需要在hibernate.cfg.xml中添加:
<propety name="Hibernate.current_session_context_class">thread</propety>
-
并当事务结束的时候【提交or回滚事务】自动关闭session,不需要手动写session.close();
-
此时session所有的crud都需要事务
dorado中
sessionFactory:dorado去负责创建和关闭。
1.1 映射表到实体类
hibernate.cfg.xml+配置
配置有两种方法:xml配置和注解配置
- xml配置:在Entity.hbm.xml中配置表和实体类的映射
- 注解配置(dorado采用):在实体类中进行注解,dorado可自动进行从数据库表到带有注解的实体类转换
hibernate.cfg.xml【放在src目录下,如果maven项目,放在src/main/resource目录下】
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- 配置hibernate核心配置文件 -->
<hibernate-configuration>
<!-- 配置hibernate数据源连接 -->
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:8080/project</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 配置sql打印、格式化 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 配置hibernate映射文件位置 xml方式 <mapping resource="com/公司名/项目名/entity/User.hbm.xml"/>-->
<!-- 配置hibernate映射 注解方式 -->
<mapping class="com.公司名.项目名.entity.User"></mapping>
</session-factory>
</hibernate-configuration>
1.2 hibernate的使用
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s= sf.openSession();
s.beginTransaction();
/*
hql:获取List<实体类>
sql:获取List<Object[]>
String hql = "from User where id=12";
List<User> = s.createQuery(hql).list();
/*
String sql = "select name,avg(age) from user where groupby name="hua"";
List<Object[]> list = s.createSQLQuery(sql).list();
for (Object[] os : list) {
for (Object filed: os) {
System.out.print(filed+"\t");
}
System.out.println("\n");
}
s.getTransaction().commit();
s.close();
sf.close();
1.3 dorado中hibernate的映射
原生的hibernate需要:hibernate.cfg.xml+配置
在dorado中使用hibernate需要:
- hibernate.cfg.xml。dorado不使用hibernate.cfg.xml,而是把相关配置放在dorado-home中的app-context文件中。
- 采用注解配置。在实体类中进行注解,dorado可自动进行从数据库表到带有注解的实体类转换
1.4 dorado中hibernate的使用
1. 复杂查询。使用原生的hibernate的sql,此时要手动启动hibernate
2. 增删改以及获取实体类的简单查询。使用dorado的封装hibernate(只能使用hql:不操作数据库,操作的是类对象)
dorado在web项目运行后会自动加载app-context的内容,自动启动hibernate
1.4.0 dorado使用原生hibernate的sql需要:hibernate.cfg.xml+注解配置
hibernate.cfg.xml放在src根目录下,如果maven项目,放在src/main/resource目录下
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- 配置hibernate核心配置文件 -->
<hibernate-configuration>
<!-- 配置hibernate数据源连接 -->
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:8080/project</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 配置sql打印、格式化 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 配置hibernate映射 注解方式 -->
<mapping class="com.公司名.项目名.entity.User"></mapping>
</session-factory>
</hibernate-configuration>
1.4.1 保存数据到数据库
@DataResolver
@Transactional
public void saveCompany(Collection<SlCompany> slCompanys) {
//存入数据库,新建账户和用户
Account account = new Account();
account.setStatus(Const.STATUS_OK);
account.setCompany(company);
account.setBalance(Const.ACCOUNT_BALANCE_ZERO);
//变成Entity
account = EntityUtils.toEntity(account);
//添加状态,是添加还是删除
EntityUtils.setState(account, EntityState.NEW);
//添加到数据库
accountDao.save(account);
//修改,新建,移动就是save,删除为delete
for(SlCompany o: slCompanys) {
//从dorado前端传过来的数据可直接EntityUtils.getState(o),否则先把o变成Entity
//o = EntityUtils.toEntity(o);EntityUtils.setState(o, EntityState.MODIFIED);
if(EntityState.DELETED.equals(EntityUtils.getState(o))){
slCompanyDao.delete(o);
}
slCompanyDao.save(o);
}
//先查看各对象的状态,再进行处理
// slCompanyDao.persistEntities(slCompanys);
//HibernateDao.persistEntities
@SuppressWarnings("unchecked")
public int persistEntities(Collection<T> entities) {
int i = 0;
for (Object entity : EntityUtils.getIterable(entities,
FilterType.DELETED)) {
delete((T) entity);
i++;
}
for (Object entity : EntityUtils.getIterable(entities,
FilterType.MODIFIED)) {
save((T) entity);
i++;
}
for (Object entity : EntityUtils
.getIterable(entities, FilterType.MOVED)) {
save((T) entity);
i++;
}
for (Object entity : EntityUtils.getIterable(entities, FilterType.NEW)) {
save((T) entity);
i++;
}
return i;
}
//
public static Iterator getIterator(Collection entities, FilterType filterType)
{
return new EntityIterator(entities, filterType);
}
//
public EntityIterator(Collection entities, FilterType filterType)
{
iterator = entities.iterator();
this.filterType = filterType;
findNext();
}
protected void findNext()
{
if (iterator.hasNext())
{
currentEntity = iterator.next();
if (currentEntity != null)
{
boolean visible = false;
EntityState state = EntityUtils.getState(currentEntity);
if (filterType == FilterType.NONE)
visible = state == EntityState.NONE;
else
if (filterType == FilterType.NEW)
visible = state == EntityState.NEW;
else
if (filterType == FilterType.MODIFIED)
visible = state == EntityState.MODIFIED;
else
if (filterType == FilterType.DELETED)
visible = state == EntityState.DELETED;
else
if (filterType == FilterType.MOVED)
visible = state == EntityState.MOVED;
else
if (filterType == FilterType.VISIBLE)
visible = state != EntityState.DELETED;
else
if (filterType == FilterType.DIRTY)
visible = state == EntityState.NEW || state == EntityState.MODIFIED || state == EntityState.DELETED || state == EntityState.MOVED;
else
if (filterType == FilterType.VISIBLE)
visible = state == EntityState.NEW || state == EntityState.MODIFIED || state == EntityState.MOVED;
else
if (filterType == FilterType.ALL)
visible = true;
if (visible)
hasNext = true;
else
findNext();
} else
{
hasNext = false;
}
} else
{
hasNext = false;
}
}
//
public static EntityState getState(Object entity)
{
EntityEnhancer entityEnhancer = getEntityEnhancer(entity);
if (entityEnhancer != null)
return entityEnhancer.getState();
else
return EntityState.NONE;
}
//
public static EntityEnhancer getEntityEnhancer(Object entity)
{
//从dorado前端传过来的如果没有经过任何处理,不是EnhanceableEntity
if (entity instanceof EnhanceableEntity)
{
EnhanceableEntity enhanceableEntity = (EnhanceableEntity)entity;
return enhanceableEntity.getEntityEnhancer();
}
//从dorado前端传过来的如果没有经过任何处理,是ProxyBeanUtils
if (ProxyBeanUtils.isProxy(entity))
{
MethodInterceptorDispatcher dispatcher = ProxyBeanUtils.getMethodInterceptorDispatcher(entity);
if (dispatcher != null)
{
org.aopalliance.intercept.MethodInterceptor mis[] = dispatcher.getSubMethodInterceptors();
org.aopalliance.intercept.MethodInterceptor arr$[] = mis;
int len$ = arr$.length;
for (int i$ = 0; i$ < len$; i$++)
{
org.aopalliance.intercept.MethodInterceptor mi = arr$[i$];
if (mi instanceof EntityEnhancer)
return (EntityEnhancer)mi;
//mi.getState()
}
}
}
return null;
}
1.4.2 查询得到List<实体类>
find(hql);
/此时SlMessage表中有外键sender关联到SlEmployee的employeeId字段,但是Hibernate在生成实体类时,没有成员变量sender,有成员变量slEmployee【SlEmployee类型】,所以使用SlMessage中的slEmployee的employeeId代替sender进行查询
String hql = "from SlMessage where slEmployee.employeeId = ?";
slMessageDao.find(page,hql,employeeId);
//部门是递归的,部门下有部门,顶端的部门没有所属部门,所以设为null,SlDept有外键parentId关联到SlDept的deptId字段,利用关联的字段进行查询
slDeptDao.find("from SlDept where slDept.deptId is null");//查找顶端的
slEmployeeDao.find("from SlEmployee where userName = '"+userName+"'");
slEmployeeDao.find(page, " from SlEmployee where 1=1 " + " AND name like '%li%' ");
slEmployeeDao.find("from SlEmployee where userName = ?",userName);
return slEmployeeDao.find("from SlEmployee where userName = ?",new Object[]{userName});
slEmployeeDao.find("from SlEmployee where userName = :userName",map);//map.get("userName")
DetachedCriteria dc = DetachedCriteria.forClass(SlEmployee.class);
if (username != null && !"".equals(username)) {
dc.add(Restrictions.eq("userName", username.toUpperCase()));
}
List<SlEmployee> employees = slEmployeeDao.find(dc);
//多个参数
slEmployeeDao.find("from SlEmployee where userName = ? and 1=?",userName,one);
slEmployeeDao.find("from SlEmployee where userName = ? and 1=?",new Object[]{"myName",1});
param.put("one", 1);
param.put("userName", "myName");
slEmployeeDao.find("from SlEmployee where userName = :userName and 1=:one",param);
原生sql的addEntity和setResultTransformer
使用原生 sql 语句进行 query 查询时,hibernate 是不会自动把结果包装成实体,可通过addEntity和setResultTransformer
addEntity
查找结果为:有表对应的实体类,需要:
- 在hibernate.cfg.xml中配置
<mapping class="com.entity.User"></mapping>
- 实体类经过dorado的自动编写hibernate注解
Stirng sql = "select * from user";
Query q = s.createSQLQuery(sql).addEntity(User.class);
List<User> list = q.list();
setResultTransformer
查找结果为:无表对应的类,要求:
public class Demo(){//类为public
//有参无参构造函数为public
public Demo(){};
}
String sql = "selest name,age from user";
Query q = s.createSQLQuery(sql)
.addScalar("name",StandardBasicTypes.STRING)
.addScalar("age",StandardBasicTypes.INTEGER)
.setResultTransformer(Transformers.aliasToBean(Demo.class));
List<Demo> list = q.list();
dorado中使用hibernate
测试
先在hibernate.cfg.xml 中添加注解:<mapping class=“com.entity.Account”></mapping>
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s= sf.getCurrentSession();//获取当前线程的session,没有的话,创建,会自动关闭session
s.beginTransaction();//开启事务
String sql = "select * from user";
List<Object[]> list = s.createSQLQuery(sql).list();
//List<User> list = s.createSQLQuery(sql).addEntity(User.class).list();
/*
String sql = "select * from user where name=? and id=?";
Ojbect[] params = new Object[]{"aini",1};
Query query = s.createSQLQuery(sql).addEntity(User.class)
if (params != null) {
if (params.length > 0) {
for (int i = 0; i < params.length; i++) {
//两种传参方式
//hql="select * from user where id=:myId"
//query.setParameter("myId",id);
query.setParameter(i, params[i]);
}
}
}
List<User> list = q.list();
*/
/*
in的两种使用
1. in的数据需要从其他表中获取
String hql="from A a where a.id in (select b.aId from B b where b.name=?)";
Query query = session.createQuery(hql);
List<A> list = query.setParameter(0, name);
2. in的数据已知
String hql="from A a where a.id in (:myList)";
Query query = session.createQuery(hql);
List<A> list = query.setParameterList("myList", List/数组);
/
for (Object[] os : list) {
for (Object filed: os) {
System.out.print(filed+"\t");
}
System.out.println("\n");
}
s.getTransaction().commit();//提交事务
// s.close(); getCurrentSession()会自动进行session的关闭
sf.close();//服务器被关闭,程 序被卸载时关闭
web项目
//sessionFactory的创建和关闭dorado负责,不关心
//只是复杂查询得到List<Object[]>是用得到HelpDao,其他都用原来的
//HelpDao
@Repository
public class HelpDao extends HibernateDao {
public List find(String sql){
return getSession().createSQLQuery(sql).list();
}
public List find(String sql, Class entity){
return getSession().createSQLQuery(sql).addEntity(entity).list();
}
public List find(String sql,Object params[]){
Query query = getSession().createSQLQuery(sql);
if (params != null) {
if (params.length > 0) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
}
return query.list();
}
public List find(String sql, Class entity, Object params[]){
Query query = getSession().createSQLQuery(sql).addEntity(entity);
if (params != null) {
if (params.length > 0) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
}
return query.list();
}
}
public class Service{
@Resource
private HelpDao helpDao;
String sql = "select * from user";
List<User> list = helpDao.find(sql,User.class);
List<Object[]> list2 = helpDao.find(sql);
for (Object[] os : list2) {
for (Object o: os) {
System.out.print(o+"\t");
}
System.out.println("\n");
}
String sql2 = "select * from user where name=? and id=?";
List<User> list3 = helpDao.fin(sql2,User.class,new Ojbect[]{"lian",1});
List<Object[]> list4 = helpDao.find(sql2,new Ojbect[]{"lian",1});
}
注意
注解的@Entity
导包:javax.persistence.Entity
不推荐使用:org.hibernate.annotations.Entity //会出错
无法保存或更新或删除
原因:没有在方法上使用@Transactional
复杂查询 在web中
使用sql,但分页麻烦
String sql="select pm.name packageName,apc.num_left numLeft,apc.package_start_time startTime from APC apc left join PM pm on apc.id1=pm.id where apc.account_id=? and pm.name=?"
Map<String,Type> map = new HashMap();
map.put("packageName", StandardBasicTypes.STRING);
map.put("numLeft", StandardBasicTypes.INTEGER);
map.put("startTime", StandardBasicTypes.STRING);
map.put("statusByte", StandardBasicTypes.BYTE);
List<Pack> list = helpDao.find(sql,Pack.class,new Object[]{accountId,name},map)
使用hql时,方便分页
利用select
//where后
String hql="from A a where a.id in (select b.aId from B b where b.name=?)";
String hql="from A a where a.age > (select b.age from B b where b.name=?)";