zoukankan      html  css  js  c++  java
  • hibernate复习第(一)天

    首先导入jar。

     这个版本是3.2.5

    开发流程:
    1、由Domain object ->mapping ->db (官方推荐)
    2、由DB开始,使用工具生成mapping和Domain object。(常用)
    3、由映射文件开始

    hibernate的bean的要求:
    1、有一个缺省的构造,也就是无参构造
    2、有一个id属性,对应数据库的主键。(可选)
    3、非final的类。对懒加载影响(可选)

    mapping映射文件。模板可以从hibernate下载文件的eq文件夹下的子文件夹中找到:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping 
        package="cn.itcast.hibernate.domain">
    
        <class name="User">
            <id name="id" >
                <generator class="native"/>
            </id>
            
            <property name="name"/>
            <property name="birthday"/>
        </class>
        
    </hibernate-mapping>

    class,对应java类,name对应类名,和package的属性组合得到类的地址

    <class name="User" table="user">可以有一个table属性,对应数据库表名,不写表示默认与类名相同

    <id name="id" column="id">可以有一个column属性,对应数据表中的列名,不写默认与类名相同

    <generator >表示以何种方式生成主键

    <property name="name" column="">属性,name对应java类的字段,column对应数据表的列名,也是可省略。如果对应的列名是唯一的的话,可以在<property 中加上unique="true"/>
    注意:这里的hibernate映射文件就是用于说明java对象与哪个表中的记录相对应,以及java对象中的各个属性分别对应表中的哪一项,不同性质的属性(例如,主键和普通属性)用不同的标签来映射,如果java对象中的某个属性不需要存储在数据库中,那么在hibernate映射文件中就不需要配置这个属性。

    两个问题:

    关于使用表名和字段与关键字冲突的问题。
    如果表名和字段与关键字啊发生冲突,解决方案有两种:
    使用column和table,改表名或字段名;
    如果表名或者字段名不允许更改,可以在table或者column中字段前面加上符号"`",例如:<class name="User" column="`user`">.这个符号是键盘中~对应的那个键在英文状态下的符号

    hibernate.cfg.xml配置文件记不住怎么办?
    这个我们一般不记,在hibernate文件夹下的etc文件夹下有一个hibernate.properties文件夹,这里所有的配置信息都可以在这里查找得到

     

    hibernate.cfg.xml文件:模板在 etc文件夹下面可以找到:

    <!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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/demo</property>
        <property name="hibernate.connection.username">guodaxia</property>
        <property name="hibernate.connection.password">961012gz</property>
        
        <property name="hibernate.hbm2ddl.auto">create</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
        
        <mapping resource="cn/itcast/hibernate/domain/User.hbm.xml"/>    
        </session-factory>
    </hibernate-configuration>

    注意:

    url中直接写jdbc:mysql:///demo表示地址是本机,端口是默认端口3306

    5个必填属性:

    url、驱动、用户名、密码、方言(方言主要是各个数据库分页语句不一样)

    hibernate.hbm2ddl.auto属性:
      4个可选值:
      create-drop(创建和删除,启动时创建,使用后删除,一般在测试使用)
      create(创建,启动时创建,使用后不删除,再次启动前删除后再创建,一般测试使用)
      update(更新)
      validate(检验映射文件与表是否对应,如果不对应报错不执行更新操作)
    show_sql属性:是否显示执行的sql语句
    <mapping resource=""/>映射文件的路径

    hibernate如何操作数据库。
        /*
             * hibernate初始化的过程,这个过程一般只做一次
             * 所以我们一般做一个工具类
             */
            Configuration cfg=new Configuration();
            cfg.configure();
            SessionFactory sf=cfg.buildSessionFactory();
            Session s=sf.openSession();

    首先得到Configuration对象,使用该构造hibernate会自动加载classpath下面的hibernate.properties文件;

    cfg.configuration();如果存在的话,hibernate自动加载classpath下的hibernate.cfg.xml配置文件。当然也可以加参数表示映射文件的文件路径和文件名,所以如果即写了hibernate.properties又写了hibernate.cfg.xml如果有相同属性配置,后者会覆盖前者。

    创建sessionFactory工厂,这个类似于JDBC的DriverManager;

    通过工厂创建session,session相当于JDBC中的Connection。

    说明:

      既然取读的是classpath下面的内容,为什么我们的配置文件都是放在src下面呢?这是因为myeclipes编译的时候会自动将src目录下的文件编译到classpath中去。

    操作数据表:使用Session接口。

    因为hibernate文件初始化比较耗费资源,我们一般书写一个工具类帮助处理:

    package cn.itcast.hibernate;
    
    import java.io.Serializable;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    public final class HibernateUtil {
        /*
         * 设计成为单例,或者将所有的放射设计成为静态的
         */
        
        private static SessionFactory sessionFactory;
        private static ThreadLocal<Session> sessionThread;/* 使用threadLocal优化连接  */
        private HibernateUtil(){
        }
        
        static{
            Configuration cfg=new Configuration();
            cfg.configure();//从classPath里面读取配置文件。如果名字不是hibernate.cfg.xml的话需要特定指出,src下的文件会自动编译到classPath中
            sessionFactory=cfg.buildSessionFactory();
            sessionThread=new ThreadLocal<Session>();
        }
        
        public static SessionFactory getSessionFactory(){
            return sessionFactory;
        }
        
        public static Session getSession(){
            Session s=sessionThread.get();
            if(s==null){
                s=sessionFactory.openSession();
            }else{
                sessionThread.set(s);
            }
            return s;
        }
    }

    java对象的几种状态:

    对象状态
    瞬时(transient):数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来的与session没有关联的对象
    持久(persistent):数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,事务没有提交,持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到);

    持久化状态的时候如果你修改了该对象会自动调用update方法。

    脱管:数据库中有数据与之对应,当前session与之无关联。save等操作后的java类或者查询得到的java类都是这种状态。托管状态的对象修改后只能是自己调用update方法才能对数据库进行修改。

    Session对象的一些常见方法: 

    Transaction beginTransaction();开启事务

    get(Class,Serializable)根据主键获取一条数据
    load(Class,Serializable)根据主键获取一条数据.具有懒加载特性。懒加载类似new一封User子类
    save(Object).保存一条数据
    persist(Object).保存一条数据。
    save和persist的区别是:在没有开启事务的情况下,save方法会先插入数据再回滚,而persist方法不会插入记录也就不需要回滚
    update(Object):将对象更新到数据库

    saveOrUpdate(Object):hibernate自动检测对象是瞬时状态还是脱管状态,然后执行insert或者update语句
    merge(Object):和saveOrUpdate类似,区别在saveOrUpdate方法操作之后会改变对象的状态,变成持久状态,而merge之后还是脱管状态

            Session s=HibernateUtil.getSession();
            User user=new User();
            user.setName("zhangSan");
            user.setBirthday(new Date());
         s.save(user);
         s.close();

    上面的代码执行完之后,sql语句正常但是数据库中却没有任何记录。这是因为:

      JDBC是自动提交的,但是hibernate的缺省将这个功能关闭,必须自己开启使用事务才会生效。事务的创建方式:

    Transaction tx=session.beginTransaction();

      如果不需要开启提交事务提交事务就可以操作数据库数据的话,注意一下你的表结构,看你的引擎

    标准的操作数据库的结构:

    static void addUser(User user){//比较规范的hibernate的一个写法
            Session s=null;
            Transaction tx=null;
            try{
                s=HibernateUtil.getSession();;
                tx=s.beginTransaction();
                s.save(user);
                user.setName("new name");//这个user是持久状态
                user.setBirthday(new Date());
                tx.commit();
            }catch(HibernateException e){
                if(tx!=null) tx.rollback();
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        }

    操作数据库的结构也可以写成这个样子:

    static void addUser1(User user){//可以简写成为这个样子,因为hibernate接到异常会自动向外抛,如果数据库没有得到事务提交信号请求会自动回滚
            Session s=null;
            Transaction tx=null;
            try{
                s=HibernateUtil.getSession();;
                tx=s.beginTransaction();
                s.save(user);
                tx.commit();
            }finally{
                if(s!=null) s.close();
            }
        }

    基本操作的一些代码:

    package cn.itcast.hibernate;
    
    import java.util.Date;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import cn.itcast.hibernate.domain.User;
    
    public class Base {
        
        public static void main(String[] args) {
            /*
             * hibernate初始化的过程,这个过程一般只做一次
             * 所以我们一般做一个工具类
             */
    //        Configuration cfg=new Configuration();
    //        cfg.configure();
    //        SessionFactory sf=cfg.buildSessionFactory();
    //        Session s=sf.openSession();
            
            Session s=HibernateUtil.getSession();
            //JDBC是自动提交的,但是hibernate的缺省将这个功能关闭,必须自己开启使用事务才会生效
            //如果必须要开启提交事务就可以操作数据库数据的话,注意一下你的表结构,看你的引擎
            User user=new User();
            user.setName("zhangSan");
            user.setBirthday(new Date());
            
    //        Transaction tx=s.beginTransaction();
    //        s.save(user);
    //        tx.commit();
    //        s.close();
    //        System.out.println("end");
            addUser(user);
            System.out.println("id:"+user.getId());
            
    //        User u=getUser(user.getId());
            User u=(User) s.load(User.class, user.getId());
            
            System.out.println("name:"+u.getName());
            
        }
        
        static void addUser(User user){//比较规范的hibernate的一个写法
            Session s=null;
            Transaction tx=null;
            try{
                s=HibernateUtil.getSession();;
                tx=s.beginTransaction();
                s.save(user);
    //            s.persist(user);
                user.setName("new name");//这个user是持久状态
                user.setBirthday(new Date());
                tx.commit();
            }catch(HibernateException e){
                if(tx!=null) tx.rollback();
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        }
        
        static void addUser1(User user){//可以简写成为这个样子,接到异常自动向外抛,如果数据库没有得到提交请求会自动回滚
            Session s=null;
            Transaction tx=null;
            try{
                s=HibernateUtil.getSession();;
                tx=s.beginTransaction();
                s.save(user);
                tx.commit();
            }finally{
                if(s!=null) s.close();
            }
        }
        
        @Test
        public void fun1(){
            System.out.println(getUser(1));
        }
        public static User getUser(int id){
            Session s=null;
            User user=null;
            try{
                s=HibernateUtil.getSession();
                user=(User) s.get(User.class, 1);
    //            user=(User) s.load(User.class,1);//这里会报错
            }finally{
                if(s!=null) s.close();
            }
            return user;
        }
    
    }
        public static void add(Object entity){
            Session s=null;
            Transaction tx=null;
            try{
                s=getSession();
                tx=s.beginTransaction();
                s.save(entity);
                tx.commit();
            }catch(HibernateException e){
                tx.rollback();
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        }
    
        public static void delete(Object entity){
            Session s=null;
            Transaction tx=null;
            try{
                s=getSession();
                tx=s.beginTransaction();
                s.delete(entity);
                tx.commit();
            }catch(HibernateException e){
                tx.rollback();
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        }
    
        public static void update(Object entity){
            Session s=null;
            Transaction tx=null;
            try{
                s=getSession();
                tx=s.beginTransaction();
                s.update(entity);
                tx.commit();
            }catch(HibernateException e){
                tx.rollback();
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        }
    
        public static Object get(Class clazz,Serializable id){
            Session s=null;
            try{
                s=getSession();
                return s.get(clazz, id);
            }catch(HibernateException e){
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        } 
    
        public static Object load(Class clazz,Serializable id){
            Session s=null;
            try{
                s=getSession();
                return s.load(clazz, id);
            }catch(HibernateException e){   
                throw e;
            }finally{
                if(s!=null) s.close();
            }
        } 
    View Code

    关于load()和get()的区别:

      两者都是根据类的字节码文件和ID得到一条数据。区别在于:

      第一点是:没有记录的情况下,load会抛出异常,get会返回空,一般采用的load方法。

      第二点是:get只返回实体对象实例。而load返回的是代理类实体对象实例。

      第三点是:get方法只能使用一级缓存。而load可以使用一级和二级缓存。

      第四点是:都是通过id得到单个对象的方法。

      第五点:load方法具有懒加载的特性,不是立即操作数据库,而是返回一个代理对象,在操作该对象的属性的时候才操作数据库将信息填入。

    关于save()和persist()的区别:

      在不开启事务的情况下,save方法会先插入数据再回滚,而persist方法不会插入记录

    update、saveOrUpdate、merge的区别见我的其他博客:

    http://www.cnblogs.com/aigeileshei/p/5796788.html

    前面学习了增删改和根据id进行查询。但是查询语句往往比较复杂,hibernate提供了两种方式进行数据库表的查询操作:HQL和Criteria

    HQL:

    面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是表,而且支持多态;
    HQL主要通过Query来操作,Query的创建方式:

    Query q=session.createQuery(hql);

    Query的主要方法:

      

    list():将query对象中的结果集变成list集合
    uniqueResult():将query对象中的结果集变成一个Object对象,当结果集中对象数>1的时候会报异常
    setXxx()和getXxx()方法,类似于pstmt的getXxx和setXxx
    setFirstResult(number);//设置query查询的结果从第多少条记录开始
    setMaxResults(number);//查询的结果多少条。使用上面的和这个方法可以进行分页,而且不限制数据库。这个分页应该是根据方言hibernate封装的

    HQL语句中占位符与命名参数的使用:

    hql语句中占位符的使用:

    String hql="from User as user where user.name=?";
    Query query=s.createQuery(hql);
    query.setString(0,name);

    这里注意,下标是从0开始的。
    命名参数的使用:
    单纯的占位符使用不是很方便,因为每一个?与数据都需要一一对应。hibernate提供了命名参数。

    String hql="from User as user where user.name=:n";
    Query query=s.createQuery(hql);
    query.setString("n"name);

    同一个命名参数可以多次使用
    命名参数在hql中=:命名参数名。格式注意正确。

    将命名参数设置进Query中们可以使用后Map结合如果参数过多的话,这样比较简便一些:

    static void qr(){
            Session s=HibernateUtil.getSession();
            String hql="from User where name=:name and age>:bj and (age-:bj)>0";
            Query query=s.createQuery(hql);
            Map <String,Object> params=new HashMap<String,Object>();
            params.put("name", "guodaxia");
            params.put("bj",12);
            query.setProperties(params);
            
            List<User> users=query.list();
        }

    hql查询的简单例子:

    package cn.itcast.hibernate;
    
    import java.util.Date;
    import java.util.Iterator;
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    
    import cn.itcast.hibernate.domain.User;
    
    public class QueryTest {
        public static void main(String[] args) {
            User user=new User();
            user.setBirthday(new Date());
            user.setName("name");
            HibernateUtil.add(user);
            
            System.out.println(query("name"));
        }
        
        static User query(String name){
            Session s=null;
            try{
                s=HibernateUtil.getSession();
    //            String hql="from User as user where user.name=?";
                String hql="from User as user where user.name=:n";
                Query query=s.createQuery(hql);
    //            query.setString(0, name);//下标从0开始
                query.setString("n", name);
                
                //设置结果集的范围,可用来分页
                query.setFirstResult(200);
                query.setMaxResults(10);
                
                List<User> list=query.list();//executeQuery()
                User user=(User) query.uniqueResult();
    //            for(Iterator<User> it=list.iterator();it.hasNext();){
    //                User user=it.next();
    //                list.add(user);
    ////                System.out.println(user);
    //            }
    //            return list.get(0);
                return user;
            }finally{
                if(s!=null) s.close();
            }
        }
    }
    View Code

    Criteria(条件查询):

      是一种比hql更加面向对象的一种方式。

      创建方式:

    Criteria crit=session.createCriteria(User.class);

    条件查询关于条件的添加与query不一样,在处理结果集方面与query基本一致。

    简单属性条件如:

    criteria.add(Restrictions.eq(propertyName,value)),
    criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName))
    Restrictions对象中封装了许多条件查询的增加条件的方法。可以配合API使用

    Criteria查询的小例子:

    package cn.itcast.hibernate;
    
    import java.util.Date;
    import java.util.List;
    
    import org.hibernate.Criteria;
    import org.hibernate.Session;
    import org.hibernate.criterion.Restrictions;
    
    import cn.itcast.hibernate.domain.User;
    
    public class Cri {
        public static void main(String[] args) {
            cri("name");
        }
        
        static void cri(String name){
            Session s=null;
            try{
                s=HibernateUtil.getSession();
                Criteria c=s.createCriteria(User.class);//条件查询,很面向对象的方式。这个接口相当于一个容器
                c.add(Restrictions.eq("name", name));//添加约束条件
                c.add(Restrictions.lt("birthday", new Date()));
                
                c.setFirstResult(0);
                c.setMaxResults(10);
                List<User> list=c.list();
                
                User u=(User)c.uniqueResult();
                System.out.println(u);
                
                for(User user:list){
                    System.out.println(user.getName());
                }
            }finally{
                if(s!=null) s.close();
            }
        }
    }
    View Code
  • 相关阅读:
    SpringBoot框架(二)
    SpringBoot框架(一)
    JavaScript语言和jQuery技术(一)
    Mysql数据库技术(四)
    Mysql数据库技术(三)
    Mysql数据库技术(二)
    Mysql数据库技术(一)
    JDBC技术(三)
    JDBC技术(二)
    JDBC技术(一)
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/5796947.html
Copyright © 2011-2022 走看看