笨人是个小白一个哈,在这里仅仅是分享下我的思路与见解,哪里有不对的还往各位前辈指导指导好让我更快的进步,以便更快的向各位前辈靠近。
这是我的整体框架:
一、首先从我的dao层开始解释吧,
package com.yibin.dao;
import java.util.List;
import com.yibin.empty.User;
/**
* 这是我们的所有自定义接口集合类
* @author 廖宜彬
*
*/
public interface Hibernateinsert {
/**
* 这是我hibernate的实体类添加操作
* @param user 传入参数类型
* @return 返回值为布尔类型
*/
boolean insertuser(User user);
/**
* 这是我hibernate的实体类更新操作
* @param user 传入参数类型为实体类类型
* @return 返回值为布尔类型
*/
boolean updateuser(User user);
/**
* 查询我们数据库内某个表的记录数
* @return
*/
int getcount();
/**
* 删除操作
* @param uid 传入一个id即 我们需要删除的记录
* @return 布尔类型
*/
boolean deleteuser(int uid);
/**
* 通过某个ID只查询单个记录
* @param uid
* @return 返回一个user对象
*/
User finduserbyid(int uid);
/**
* 该方法是实现我们查询数据库的所有记录,实现了通过分页、模糊查询
* @param page 页数
* @param pagecount 每页显示条数
* @param ulike 模糊查询输入内容
* @return 返回结果是个集合
*/
List<User> findalluser(Integer page,Integer pagecount,String ulike);
}
二、以下是我的dao层实现类
package com.yibin.dao;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.yibin.empty.User;
import com.yibin.session.HibernateSessionFactory;
/**
* 这是我们的接口实现类
* @author 廖宜彬
*时间:2018年6月19日11:57:27
*/
public class Insertdaoimpl implements Hibernateinsert {
@Override
public boolean insertuser(User user) {
// TODO Auto-generated method stub
Transaction tx=null;
try {
Session session=HibernateSessionFactory.creSession();
tx=session.beginTransaction();
session.save(user);
tx.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
@Override
public boolean updateuser(User user) {
Transaction tx=null;
Session session=null;
try {
session=HibernateSessionFactory.creSession();
tx=session.beginTransaction();
session.update(user);
tx.commit();
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
HibernateSessionFactory.closesession(session);
}
return true;
}
@Override
public int getcount() {
Session session=null;
session=HibernateSessionFactory.creSession();
Query createQuery = session.createQuery("select count(*) from User");
Object us=createQuery.uniqueResult();
Long count=(Long)us;
return count.intValue();
}
@Override
public boolean deleteuser(int uid) {
Session session=HibernateSessionFactory.creSession();
User user=new User();
user.setUid(uid);
try {
//开始我们的重点操作了
//删除某个记录前我们需要先判断该记录是否存在然后在执行相应的操作
//根据id值向数据库中查询出来对应的对象。可以采用两种方式一是session的get方法,一个是session的load(也称懒加载)方法。
Object object = session.get(User.class, uid);
//get与load的区别:get方法加载的时候会立刻发出sql语句去查询,而load方法在执行的时候没有立刻的发出sql去查询,
//生成一个代理User,没有生成真正的User。当我们真正的去用这个user的时候才会加载真正的User。Load()支持延迟加载,
//而Get()不支持延迟加载。Get加载的对象不存在时返回的是null对象,而Load()加载对象不存在时会抛出ObjectNotFoundException异常。
session.evict(object);
//该方法是一定要写的,否则执行删除操作时会报错。其原因是该id已经被占用了。
if (object!=null) {
session.beginTransaction();
session.delete(user);
session.getTransaction().commit();
return true;
}else {
return false;
}
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
//释放资源
HibernateSessionFactory.closesession(session);
}
}
@Override
public User finduserbyid(int uid) {
Session session=HibernateSessionFactory.creSession();
User user=new User();
user=(User)session.get(User.class, uid);
return user;
}
@Override
public List<User> findalluser(Integer page, Integer pagecount, String ulike) {
Session session=HibernateSessionFactory.creSession();
Query createQuery = session.createQuery("from User where uname like concat('%',?,'%')");
if (ulike==null)
ulike="";
createQuery.setParameter(0, ulike);
if (ulike!=null) {
createQuery.setFirstResult((page-1)*pagecount);
createQuery.setMaxResults(pagecount);
}
return createQuery.list();
}
}
Transaction tx=null; 创建一个事物对象
Session session=HibernateSessionFactory.creSession(); 创建一个java与数据库产生会话的会话对象,其中HibernateSessionFactory是我的公共类,封装了一些方法。
tx=session.beginTransaction(); 开启我们的事物
注意:我们的hibernate框架是面向对象的
session.save(user); 通过我们的会话对象调用我们hibernate框架里的添加方法save(),把session对象加入到缓存中使它变为持久化对象。或者使用saveOrUpdate()方法该方法兼具save()和update()功能,会自动判断是游离对象还是持久化对象。
tx.commit(); 将我们的事务提交(实现我们的增删改都需要提交事务)
public int getcount();该方法是查询我们数据库内表的记录数,刚开始我以为不可以实现后来通过查阅测试发现还是可以的在这里是通过HQL来实现的。(关于HQL、SQL、QBC下篇博客会进行解释)。
Query createQuery = session.createQuery("select count(*) from User");
在这里的User是我们的实体类名并不是表名,需要稍微注意下。另外这里也有个知识点是关于使用count(*)和count(1)的区别,两者都是统计我们数据库的记录数的,只不过在查询我们大型数据库表时使用count(1)的效率会比使用count(*)的效率高许多。(我有个疑惑就是为什么我用hql时使用count(1)会报错?还望各位前辈指点一二)
Object us=createQuery.uniqueResult();
因为我查询所得的结果是唯一的,因此采用了uniqueResult()方法,它的返回类型是Object类型。但是因为我们的结果是个int类型,所以需要进行转化
删除操作:
boolean deleteuser(int uid)
根据ID删除我们的记录
在删除我们的记录时要先判断该记录是否存在,在操作之前先说说我们的根据ID向数据库查询的两个方法的区别:
首先根据id值向数据库中查询出来对应的对象。可以采用两种方式一是session的get方法,一个是session的load(懒加载)方法。
Session的Get方法:调用这个方法会返回一个Object对象。然后我们对其强制转换。User user = (User)session.get(User.class,” uid”); 当我们传递id值在数据中查找没有相应的结果时,get方法会返回一个null值。
区别:get方法加载的时候会立刻发出sql语句去查询,而load方法在执行的时候没有立刻的发出sql去查询,生成一个代理User,没有生成真正的User。当我们真正的去用这个user的时候才会加载真正的User。Load()支持延迟加载,而Get()不支持延迟加载。Get加载的对象不存在时返回的是null对象,而Load()加载对象不存在时会抛出ObjectNotFoundException异常。个人建议使用get,如果使用load当你输入一个不存在的ID时,控制台会抛出ObjectNotFoundException异常,毕竟大家都不喜欢它报红嘛。当然你也可以在try catch语句块里,去掉异常信息输出。(eg:e.printStackTrace();)
如果使用get的话记得一定要加上这一句session.evict(object);如果没有这一句是会报错的。原因很简单就和我们打开了某个文档后又选择删除该文档,因为用get时它已经使用了该ID去查询,已经被占用了。所以执行删除时出错了。session.evict(object);这句话的作用就是将object对象的缓存清空使其处于托管状态(不要用clear()它是清空所有缓存)
查询操作:
在这里做的查询分为两种,一个是根据ID查询单个记录;二是具备分页、模糊的查询所有。首先是单个查询:
public User finduserbyid(int uid) {
Session session=HibernateSessionFactory.creSession();
User user=new User();
user=(User)session.get(User.class, uid);
return user;
}
其次是我们的查询所有,这里我传入了三个参数一个是显示页数(page)、每页显示条数(pagecount)模糊查询输入内容(Ulike)这里呢分页查询有个通用公式:(显示页数-1)*每页显示数目。即(page-1)*pagecount。
if (ulike==null)
ulike="";
createQuery.setParameter(0, ulike);
这一步处理是为了防止模糊查询时输入关键字null,如果输入null在SQL语句中查询的结果是没有的。因此我们需要处理这一步,如果输入则将其赋值为“”使其查询所有。在这里呢并不需要输入limit语句,hibernate里有可直接输入。createQuery.setFirstResult((page-1)*pagecount);便是显示页数即你想看第几页。createQuery.setMaxResults(pagecount);则是我们当前页面需要显示的数目。最后将我们查询所得的结果转化为list,可直接使用list方法。当然也可以使用迭代器遍历输出。可看以下代码:
publicvoid testQuery1()
{
Sessionsession =null;
try
{
session= HibernateUtils.getSession();
session.beginTransaction();
//参数是一个字符串,是HQL的查询语句.注意此时的的UserU为大写,为对象的,而不是表的.
Queryquery = session.createQuery("from User");
//使用List方法.
ListuserList = query.list();
//迭代器去迭代.
for(Iteratoriter=userList.iterator();iter.hasNext();)
{
Useruser =(User)iter.next();
System.out.println("id="+user.getId() + "name="+user.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
三、公共类(我们所有方法需要使用到的公共部分代码)
package com.yibin.session;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 该类为我们的公共类,封装我们的公共部分代码以达到减少代码的重复
* @author 廖宜彬
*时间:2018年6月19日12:03:19
*/
public class HibernateSessionFactory {
//创建我们的工厂对象
private static SessionFactory sessionFactory=null;
//声明一个静态块
static {
//创建我们hibernate的config对象
Configuration config=new Configuration();
//加载我们的hibernate配置文件
config.configure();
sessionFactory=config.buildSessionFactory();
}
/**
* 创建我们与数据库的会话对象
* @return
*/
public static Session creSession(){
return sessionFactory.openSession();
}
/**
* 释放资源
* @param session
*/
public static void closesession(Session session){
if (session!=null) {
session.close();
}
}
}
四、service层
package com.yibin.service;
import java.util.List;
import com.yibin.empty.User;
/**
* 这是service层
* @author 廖宜彬
*时间:2018年6月19日12:00:37
*使用MVC思想实现
*/
public interface Insertservice {
public boolean insertuser(User user);
boolean updateuser(User user);
int getcount();
boolean deleteuser(int uid);
User finduserbyid(int uid);
List<User> findalluser(Integer page, Integer pagecount, String ulike);
}
五、service层的实现类
package com.yibin.service;
import java.util.List;
import com.yibin.dao.Hibernateinsert;
import com.yibin.dao.Insertdaoimpl;
import com.yibin.empty.User;
/**
* service接口的实现类
* @author 廖宜彬
*时间:2018年6月19日14:07:57
*/
public class Insertserviceimpl implements Insertservice {
//因为hibernate框架里没有xml文件映射所以直接将该接口实现了
private Hibernateinsert hinsert=new Insertdaoimpl();
@Override
public boolean insertuser(User user) {
return hinsert.insertuser(user);
}
@Override
public boolean updateuser(User user) {
return hinsert.updateuser(user);
}
@Override
public int getcount() {
return hinsert.getcount();
}
@Override
public boolean deleteuser(int uid) {
return hinsert.deleteuser(uid);
}
@Override
public User finduserbyid(int uid) {
return hinsert.finduserbyid(uid);
}
@Override
public List<User> findalluser(Integer page, Integer pagecount, String ulike) {
return hinsert.findalluser(page, pagecount, ulike);
}
}
六、测试类
package com.yibin.test;
import org.junit.Test;
import com.yibin.empty.User;
import com.yibin.service.Insertservice;
import com.yibin.service.Insertserviceimpl;
public class Testmvc {
private static Insertservice iuservice=new Insertserviceimpl();
public static void update(){
// TODO Auto-generated method stub
User user=new User();
user.setUid(3);
user.setUname("逗比东");
if (iuservice.updateuser(user)) {
System.out.println("OK");
}else {
System.out.println("NO");
}
}
public void countsel(){
System.out.println(iuservice.getcount());
}
public void deleteuser() {
int uid=1;
if (iuservice.deleteuser(uid)) {
System.out.println("删除成功!");
}else {
System.out.println("删除失败!");
}
}
public void findbyuser() {
int uid=2;
System.out.println(iuservice.finduserbyid(uid));
}
@Test
public void showalluser() {
System.out.println(iuservice.findalluser(1, 3, "逗"));
}
}
该测试类为了方便测试没有写主方法,测试某个方法时,在它前面加上一个@Test就相当于一个主方法,并将其所在包导入。右键运行即可。
七、hibernate.cfg.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping resource="com/yibin/empty/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
这是我hibernate的配置,从上往下的property分别是:数据库连接驱动、本地数据库、数据库用户名、数据库密码、hibernate方言、控制台输出SQL语句、根据实体类自动创建表。
hibernate方言(dialect)是我们的数据库适配器,根据我们不同的数据库转化为对应的方言。
hbm2ddl.auto的四个属性简述:
create:
每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行
create-drop :
每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除
update:
validate :
每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
<mapping resource="com/yibin/empty/User.hbm.xml"/>这句可以写也可以不写,如果没写我们需要在公共类配置里需要通过addclass()方法加载,并且要求User.hbm.xml是和实体类处于同一个包下。
八、实体类的xml配置(User.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.yibin.empty">
<class name="User">
<id name="uid">
<generator class="identity"></generator>
</id>
<property name="uname"></property>
<property name="upwd" not-null="true">
<column name="upwd" default="123456"></column>
</property>
</class>
</hibernate-mapping>
这个是我实体类的配置,其命名有标准格式。一定得是(*.hbm.xml)格式,包括hibernate配置命名也是有标准格式的(hibernate.cfg.xml)。
<hibernate-mapping package="com.yibin.empty">这里的package就相当于我们mybatis配置里的取别名。因为我是根据我的实体类来自动创建表的,所以没有与数据库的字段一一对应。
这里简单说下generator属性,它有7种class其作用分别是:
1、identity:用于MySql数据库。特点:递增
注:对于MySql数据库使用递增序列时需要在建表时对主键指定为auto_increment属性。
2、sequence:用于Oracle数据库
3、native:跨数据库时使用,由底层方言产生。
注:使用native时Hibernate默认会去查找Oracle中的hibernate_sequence序列。 如果Oracle中没有该序列,连Oracle数据库时会报错。
4、hilo:通过高低位合成id,先建表hi_value,再建列next_value。必须要有初始值。
5、sequencehilo:同过高低位合成id,建一个sequence序列,不用建表。
6、assigned:用户自定义id;
7、foreign:用于一对一关系共享主健时,两id值一样。
在这里的default属性是无效的,当时我为了给某个字段设定默认值测试用的。如果你需要给某个字段设定默认值,有个很简单的方法,直接在该实体类里对应字段的成员变量名赋初值即可(想想我当时为了搞这个花了大半天时间)
实体类与表一一对应的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 这个配置是为了将我们的实体类和我们表的关系一一映射 -->
<hibernate-mapping>
<!-- 在这里配置的是我们的表映射,因为我们的hibernate是面向对象的框架,所以这里配置的映射是我们的实体类 -->
<!-- 有多个表则配置多个class name是我们的实体类 ,table则是我们的表名-->
<class name="com.yibin.empty.User" table="stu">
<id name="uid" column="id">
<generator class="native"></generator>
</id>
<property name="uname" column="name"></property>
<property name="upwd" column="course"></property>
</class>
</hibernate-mapping>