zoukankan      html  css  js  c++  java
  • Hibernate

    Hibernate框架以完全面向对象的方式,提供了操作数据库的简便方法

    1.数据库连接、实体类映射配置文件

    注意,该配置文件必须放在src目录下,名称必须为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-configuration>
     
        <session-factory>
            <!-- 数据库连接设置 -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/hibernate?characterEncoding=UTF-8</property>
            <property name="connection.characterEncoding">utf-8</property>
            <property name="connection.username">root</property>
            <property name="connection.password">123456</property>
            <!-- SQL dialect -->
            <!--本地方言,即告诉框架使用哪种数据库语言-->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <!--这是Hibernate事务管理方式,即每个线程一个事务-->
         <property name="current_session_context_class">thread</property>
            <!--这表示是否在控制台显示执行的sql语句-->
            <property name="show_sql">true</property>
            <!-- 这表示是否会自动更新数据库的表结构,有这句话,其实是不需要创建表的,
            因为Hibernate会自动去创建表结构 -->
            <property name="hbm2ddl.auto">update</property>
            <!--实体类映射配置文件路径,一个实体类一个配置文件-->
            <mapping resource="com/domain/Customer.hbm.xml" />
        </session-factory>
     
    </hibernate-configuration>    

    2.实体类配置文件

    必须放在该实体类所在的包下,名称必须为 类名.hbm.xml,例如Customer.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     <!-- 填写包名 -->
    <hibernate-mapping package="com.domain">
        <!-- name属性值对应类名 table属性值对应表名 -->
        <class name="Customer" table="cst_customer">
            <!-- 主键 实体类属性名 对应的字段名-->
            <id name="cust_id" column="cust_id">
                <!--  native意味着id的自增长方式采用数据库的本地方式 -->
                <generator class="native">
                </generator>
            </id>
            <!-- name属性值对应实体类属性名 column对应字段名,必须严格一一对应 -->
            <!--column属性可以不写,默认字段名为实体类属性名  -->
            <!-- 注意一点,有多少个字段名,在插入数据时,就会插入多少个字段值! -->
            <property name="cust_name"  column="cust_name" />
            <!--  <property name="cust_user_id" column="cust_user_id" />
            <property name="create_id" column="create_id"></property>
            <property name="cust_source" column="cust_source"></property>
            <property name="cust_industry" column="cust_industry"></property>
            <property name="cust_level" column="cust_level"></property>
            <property name="cust_linkman" column="cust_linkman"></property>
            <property name="cust_phone" column="cust_phone"></property>
            <property name="cust_mobile" column="cust_mobile"></property>-->
        </class>
         
    </hibernate-mapping>

    3.向数据库内插入一条数据

    新建一个实体类Customer

    public class Customer {
    private long cust_id;
    private String cust_name;
    private long cust_user_id;
    private long create_id;
    private String cust_source;
    private String cust_industry ;
    private String cust_level;
    private String cust_linkman;
    private String cust_phone;
    private String cust_mobile;
    public Customer(long cust_id, String cust_name, long cust_user_id, long create_id, String cust_source,
            String cust_industry, String cust_level, String cust_linkman, String cust_phone, String cust_mobile) {
        super();
        this.cust_id = cust_id;
        this.cust_name = cust_name;
        this.cust_user_id = cust_user_id;
        this.create_id = create_id;
        this.cust_source = cust_source;
        this.cust_industry = cust_industry;
        this.cust_level = cust_level;
        this.cust_linkman = cust_linkman;
        this.cust_phone = cust_phone;
        this.cust_mobile = cust_mobile;
    }
    public Customer() {
        super();
    }
    @Override
    public String toString() {
        return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_user_id=" + cust_user_id
                + ", create_id=" + create_id + ", cust_source=" + cust_source + ", cust_industry=" + cust_industry
                + ", cust_level=" + cust_level + ", cust_linkman=" + cust_linkman + ", cust_phone=" + cust_phone
                + ", cust_mobile=" + cust_mobile + "]";
    }
    public long getCust_id() {
        return cust_id;
    }
    public void setCust_id(long cust_id) {
        this.cust_id = cust_id;
    }
    public String getCust_name() {
        return cust_name;
    }
    public void setCust_name(String cust_name) {
        this.cust_name = cust_name;
    }
    public long getCust_user_id() {
        return cust_user_id;
    }
    public void setCust_user_id(long cust_user_id) {
        this.cust_user_id = cust_user_id;
    }
    public long getCreate_id() {
        return create_id;
    }
    public void setCreate_id(long create_id) {
        this.create_id = create_id;
    }
    public String getCust_source() {
        return cust_source;
    }
    public void setCust_source(String cust_source) {
        this.cust_source = cust_source;
    }
    public String getCust_industry() {
        return cust_industry;
    }
    public void setCust_industry(String cust_industry) {
        this.cust_industry = cust_industry;
    }
    public String getCust_level() {
        return cust_level;
    }
    public void setCust_level(String cust_level) {
        this.cust_level = cust_level;
    }
    public String getCust_linkman() {
        return cust_linkman;
    }
    public void setCust_linkman(String cust_linkman) {
        this.cust_linkman = cust_linkman;
    }
    public String getCust_phone() {
        return cust_phone;
    }
    public void setCust_phone(String cust_phone) {
        this.cust_phone = cust_phone;
    }
    public String getCust_mobile() {
        return cust_mobile;
    }
    public void setCust_mobile(String cust_mobile) {
        this.cust_mobile = cust_mobile;
    }
    }

    实体类的基本数据类型请使用其包装类,因为框架生成对象,属性值有可能为null,如果是基本数据类型会报错。上例中如果把long修改为Long,但是get set 构造器没同步修改,会造成报错!

    具体操作:

    public class demo {
    //Junit注释当前类为测试类
        @Test
        public void saveCustomer() {
            Configuration c = new Configuration();//加载配置文件
            c.configure();//加载配置文件
            //工厂模式
            SessionFactory factory = c.buildSessionFactory();
            Session session = factory.openSession();//开启一个会话
            Transaction transaction = session.beginTransaction();//开启事务
            Customer customer = new Customer();
            customer.setCust_name("Harry");
            session.save(customer);//保存
            transaction.commit();//提交
            session.close();//关闭会话
            factory.close();//关闭工厂
        }
        
    }

     获取数据:

     Customer customer = session.get(Customer.class,1);

    获取id为1的数据,封装为对象,利用该对象可以实现修改、删除等操作

    注意,id数值类型一定要填写正确,例如id为Long,则应输入1L

    修改:

     Customer customer = session.get(Customer.class,1);
     customer.setCust_name("张三");
     session.update(customer);

    这里注意,即使不调用update方法,数据也会自行修改。

    删除:

    session.delete(customer);

    2.Util封装

    public class HibernateUtil {
        private static SessionFactory sf;
        static {
            //加载配置
            Configuration cfg = new Configuration().configure();//一定不要忘了调用configure方法,否则会报错!
            sf = cfg.buildSessionFactory();
        }
        //获取session
        public static Session openSession() {
            return sf.openSession();
        }
        //获取一个与当前线程绑定的Session
        public static Session getCurrentSession() {
            return sf.getCurrentSession();
        }
    }

    3.对象状态

    public class TestDemo {
        @Test
        public void test() {
            Session session = HibernateUtil.openSession();
            Transaction transaction = session.beginTransaction();
            Customer  c = new Customer();
            c.setCust_name("张三");//瞬时状态
            session.save(c);//持久化状态
            transaction.commit();
            session.close();
           //脱管状态
        }
    }        

    瞬时状态:设置对象属性时,数据库中没有该条数据,此时对象是瞬时的。

    持久化状态:此时对象存在于数据库,同时与session产生了联系,此时对象是持久化状态。

    脱管状态:session关闭,对象与session失去联系,脱离了管理,此时对象是脱管状态。

    4.一级缓存

    @Test
        public void get() {
            Session session = HibernateUtil.openSession();
            Transaction transaction = session.beginTransaction();
            System.out.println("第一次查找");
            Customer c1 = (Customer)session.get(Customer.class, 1L);
            System.out.println("第一次查询对象哈希:"+c1.hashCode());
            System.out.println("第二次查找");
            Customer c2 = (Customer)session.get(Customer.class, 1L);
            System.out.println("第一次查询对象哈希:"+c2.hashCode());
            transaction.commit();
            session.close();
        }

    输出结果:

    第一次查找
    Hibernate: select customer0_.cust_id as cust1_0_0_, customer0_.cust_name as cust2_0_0_, customer0_.cust_user_id as cust3_0_0_, customer0_.create_id as create4_0_0_, customer0_.cust_source as cust5_0_0_, customer0_.cust_industry as cust6_0_0_, customer0_.cust_level as cust7_0_0_, customer0_.cust_linkman as cust8_0_0_, customer0_.cust_phone as cust9_0_0_, customer0_.cust_mobile as cust10_0_0_ from cst_customer customer0_ where customer0_.cust_id=?
    第一次查询对象哈希:1881561036
    第二次查找
    第一次查询对象哈希:1881561036

    第一次查询后,对象被存入session一级缓存,如果后续操作还需要该对象,则直接从缓存中取该对象,对象哈希值一样。

    快照:

    连续修改两次数值

        @Test
        public void update() {
            Session session = HibernateUtil.openSession();
            Transaction transaction = session.beginTransaction();
            Customer c = (Customer)session.get(Customer.class, 2L);
            c.setCust_name("李四");
            c.setCust_name("小芳");
            //session.update(c);//可以不写
            transaction.commit();
            session.close();
        }

    控制台输出:

    Hibernate: select customer0_.cust_id as cust1_0_0_, customer0_.cust_name as cust2_0_0_, customer0_.cust_user_id as cust3_0_0_, customer0_.create_id as create4_0_0_, customer0_.cust_source as cust5_0_0_, customer0_.cust_industry as cust6_0_0_, customer0_.cust_level as cust7_0_0_, customer0_.cust_linkman as cust8_0_0_, customer0_.cust_phone as cust9_0_0_, customer0_.cust_mobile as cust10_0_0_ from cst_customer customer0_ where customer0_.cust_id=?
    Hibernate: update cst_customer set cust_name=?, cust_user_id=?, create_id=?, cust_source=?, cust_industry=?, cust_level=?, cust_linkman=?, cust_phone=?, cust_mobile=? where cust_id=?

    查询时,一个对象被放入session缓存,一个对象副本被存入快照区,当快照区的对象与缓存区的对象值不同时,数据被刷新到数据库,另外实际执行的语是是修改为小芳的那一条,如果我们先把名字改为小明,在改为李四(原始数据),则只会执行查询语句,因为快照区与缓存区内的对象没有变化。

    这也就是之前我们没有执行uodate方法,数据依然会被更新的原因!

    这样可以减少执行不必要的语句,提高效率。

     5.事务操作、隔离等级

    为了防止并发操作引起的脏读、幻读等情况,要设置隔离等级 1,2,4,8

    <!--这是Hibernate事务管理方式,即每个线程一个事务-->
    <property name="current_session_context_class">thread</property>
    获取session时要getCurrentSession,该种方式获取的session不要手动关闭,会自动关闭!
    6.条件查询
    HQL语言查询,hibernate自创的面向对象查询语言:
    注意 from后面跟的是类名,不是表名!
    @Test
        public void test2() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            //hql查询
            String hql = "from Customer";
            Query qr = session.createQuery(hql);
            List<Customer> customer = qr.list();
            System.out.println(customer);
            t.commit();
            session.close();
        }
        @Test
        public void test3() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            //hql条件查询
            String hql = "from Customer where cust_name=?";
            Query qr = session.createQuery(hql);
            qr.setParameter(0, "李四");//占位符开始位置基0
            Customer c = (Customer) qr.uniqueResult();
            System.out.println(c);
            t.commit();
            session.close();
        }
        @Test
        public void test4() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            //hql分页查询
            String hql = "from Customer";
            Query qr = session.createQuery(hql);
            qr.setFirstResult(0);
            qr.setMaxResults(2);
            List<Customer> customer = qr.list();
            System.out.println(customer);
            t.commit();
            session.close();
        }
    使用Criteria进行数据查询 :Criteria 完全是 面向对象的方式在进行数据查询,将不再看到有sql语句的痕迹
      @Test
        public void test5() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            Criteria c = session.createCriteria(Customer.class);
            c.add(Restrictions.eq("cust_id", 2L));
            Customer customer = (Customer) c.uniqueResult();
            System.out.println(customer);
            t.commit();
            session.close();
        }

    SQL原生查询:

        @Test
        public void test6() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            String sql = "select * from cst_customer";
            SQLQuery sq = session.createSQLQuery(sql);
            List<Object[]> list = sq.list();
            for(Object[] o:list) {
                System.out.println(Arrays.toString(o));
            }
            t.commit();
            session.close();
        }

    结果封装为指定对象

        @Test
        public void test7() {
            Session session = HibernateUtil.openSession();
            Transaction t = session.beginTransaction();
            String sql = "select * from cst_customer";
            SQLQuery sq = session.createSQLQuery(sql);
            sq.addEntity(Customer.class);//封装为Customer对象
            List<Customer> list = sq.list();
            for(Customer c:list) {
                System.out.println(c);
            }
            t.commit();
            session.close();
        }
     
  • 相关阅读:
    linux2.6.24.3下移植SD/MMC到S3C2440上的全历程
    设置装备布置了下双表示器
    Virtual Box 1.5.0 - 实用的“无缝窗口”
    oracle DB LINK 运用
    Linux下的tidy安置
    Linux效劳器装机安全疾速进阶指南(2)
    Linux下历程间通信
    Firefox 3 CSS Hack
    Linux下的搜刮东西find根基用法
    Linux效能器装机平安快速进阶指南(3)
  • 原文地址:https://www.cnblogs.com/whwjava/p/9107451.html
Copyright © 2011-2022 走看看