HIBERNATE知识复习记录1-连接及常用方法

  要去面试了,复习一下HIBERNATE的相关知识吧,原来边看视频边写的代码如下,已经分不清先后次序了,大致看一看吧。

  先看下总的配置文件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="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="hibernate.connection.password">tiger</property>
        <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        <property name="hibernate.connection.username">scott</property>
<!--    <property name="hibernate.default_schema">hibernate5</property>    --> 
       <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
        
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        
        <!-- 指定数据表的生成策略
            create: 每次操作都重新删除新建表
            update: 如果表结构有改变,将进行更新,但不会删除原来被更新的行与列
            create-drop: 每次操作时新建表,SESSION关闭时会删除表
            validate: 会检查表结构是否发生变化,若有变化会抛出异常,但不会修改表结构
        -->
        <property name="hbm2ddl.auto">update</property>
        
        <!-- 设置hibernate的事务隔离级别
            1: 读未提交
            2: 读已提交
            4: 可重复读
            8: 序列化
         -->
        <property name="hibernate.connection.isolation">2</property>
        
        <!-- 删除对象后使其OID置为null -->
        <property name="hibernate.use_identifier_rollback">true</property>
        
        <!-- 配置管理session的方式-->
        <property name="current_session_context_class">thread</property>
        
        <!-- 启用二级缓存  -->
        <property name="cache.use_second_level_cache">true</property>
        
        <!-- 配置使用的二级缓存的产品  -->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        
        <!-- 配置启用查询缓存 -->
        <property name="cache.use_query_cache">true</property>

        <!-- <property name="hibernate.c3p0.max_size">10</property>
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <property name="hibernate.c3p0.idle_test_period">2000</property>
        <property name="hibernate.c3p0.timeout">2000</property>
        <property name="hibernate.c3p0.max_statements">10</property> -->
        
        <!-- invalid for mysql, valid for oracle -->
        <property name="hibernate.jdbc.fetch_size">100</property>
        <property name="hibernate.jdbc.batch_size">30</property>
        
        <!-- 指定关联的 .hbm.xml 文件 -->
        <!-- <mapping resource="hibernate/helloworld/News.hbm.xml" />
        <mapping resource="hibernate/helloworld/Worker.hbm.xml"/>
        <mapping resource="ntoone/Customer.hbm.xml"/>
        <mapping resource="ntoone/Order.hbm.xml"/> -->
        <!-- <mapping resource="ntoone/both/Customer.hbm.xml"/>
        <mapping resource="ntoone/both/Order.hbm.xml"/> -->
        <!-- <mapping resource="onetoone/foreign/Department.hbm.xml"/>
        <mapping resource="onetoone/foreign/Manager.hbm.xml"/>
        <mapping resource="onetoone/primary/Department.hbm.xml"/>
        <mapping resource="onetoone/primary/Manager.hbm.xml"/> -->
        <!-- <mapping resource="nton/Category.hbm.xml"/>
        <mapping resource="nton/Item.hbm.xml"/> 
        <mapping resource="unionclass/Person.hbm.xml"/>
        <mapping resource="strategy/Customer.hbm.xml"/>
        <mapping resource="strategy/Order.hbm.xml"/>-->
        <mapping resource="twolevelcache/Department.hbm.xml"/>
        <mapping resource="twolevelcache/Employee.hbm.xml"/>
        <!-- 二级缓存相关配置 -->
        <class-cache usage="read-write" class="twolevelcache.Employee"/>
        <class-cache usage="read-write" class="twolevelcache.Department"/>
        <collection-cache usage="read-write" collection="twolevelcache.Department.emps"/>
         
    </session-factory>
</hibernate-configuration>

  其中我觉得比较重要少见的是:

  

    <!-- 删除对象后使其OID置为null -->
        <property name="hibernate.use_identifier_rollback">true</property>
    <!-- 设置hibernate的事务隔离级别
            1: 读未提交
            2: 读已提交
            4: 可重复读
            8: 序列化
         -->
        <property name="hibernate.connection.isolation">2</property>
    <!-- 配置管理session的方式-->
        <property name="current_session_context_class">thread</property>
    <!-- 二级缓存相关配置 -->
        <class-cache usage="read-write" class="twolevelcache.Employee"/>
        <class-cache usage="read-write" class="twolevelcache.Department"/>
        <collection-cache usage="read-write" collection="twolevelcache.Department.emps"/>

  先看下hibernate包下面的内容。

  大致看一下吧,不去找什么资料解释了,权且知其然吧,也没有什么延伸扩展,文末会有相关代码的下载地址。

  先看第一个dao子包:

  HibernateTest.java

package hibernate.dao;

import java.sql.Connection;
import java.sql.SQLException;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import hibernate.util.HibernateUtils;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
    @Test
    public void testManageSession()
    {
     // 这个session是通过getCurrentSession()方法创建的,所以是通过thread来管理的 Session session
= HibernateUtils.getInstance().getSession(); System.out.println("-->" + session.hashCode()); Transaction transaction = session.beginTransaction(); DepartmentDao departmentDao = new DepartmentDao(); Department dept = new Department(); dept.setName("ATGUIGU"); departmentDao.save(dept); // 若SESSION是由THREAD来管理的,则提交事务或回滚时SESSION已经关闭 transaction.commit(); System.out.println(session.isOpen()); } @Test public void testBatch() {
     // 通过该方法可以使用原生的onnection对象来进行批处理操作 session.doWork(
new Work(){ @Override public void execute(Connection connection) throws SQLException { // according to primitive jdbc api, most efficient, swiftest // see http://blog.csdn.net/huaguoming/article/details/8496398 for help } }); } }

  下面看一下hibernate映射文件。

  Department.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-29 2:43:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.dao">
    <class name="Department" table="DEPARTMENT">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
     <!-- 字段名是emps,对应的表是EMPLOYEE表,inverse="true"说明由Employee对象来维持一对多的关系,即通过
        EMPLOYEE表的DEPT_ID即Employee类的deptId字段来联系DEPARTMENT,lazy="true"说明是懒加载,在获取
        Department对象的时候并不会同时获取关联表EMPLOYEE中相应的存储在emps中的内容,只有真正用到emps对象
        的时候才会查询数据库获取相应数据。
     --> <set name="emps" table="EMPLOYEE" inverse="true" lazy="true"> <key><column name="DEPT_ID" /></key> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>

  其中生成id的方式设置成了native,也就是由相应数据库自己决定生成id的方式。

  其中还有一个一对多映射。

  Employee.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-29 2:43:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.dao">
    <class name="Employee" table="EMPLOYEE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="salary" type="float">
            <column name="SALARY" />
        </property>
        
        <property name="email" type="java.lang.String">
            <column name="EMAIL" />
        </property>
        
    <!--
      dept属性对应多个Employee对象,关于fetch几种方式的不同,可以见下面的文章
      http://blog.csdn.net/haolongabc/article/details/21629889
     --> <many-to-one name="dept" class="Department" fetch="join"><!-- join select subselect--> <column name="DEPT_ID" /> </many-to-one> </class>
  <!-- 一种HQL检索方式,参见下面的文章
     https://www.cnblogs.com/linyueshan/p/5819801.html
--> <query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal]]></query> </hibernate-mapping>

  相应的有一个多对一关系, 上面有相关解释。

  下面再看一下helloworld子包。

  HibernateTest.java

package hibernate.helloworld;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.sun.media.jfxmedia.control.VideoDataBuffer;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
  /**
   * get方法
   */ @Test
public void testGet() { System.out.println("test"); // 4. 执行保存操作 // News news = new News("Java", "ATGUIGU", new Date(new java.util.Date().getTime())); // session.save(news); News new2 = (News)session.get(News.class, 1); System.out.println(new2); News new3 = (News)session.get(News.class, 1); System.out.println(new3); } /** * flush: 使数据表中的记录和session缓存中的对象的状态保持一致, * 为了保持一致,则是可能会发送对应的sql语句 * 1. 调用transaction的commit()方法中:先调用session的 * flush方法,再提交事务。 * 2. flush方法可能会发送sql,不会提交事务 * 3. 注意:在未提交事务或显示的调用session.flush()方法之前,也有可 * 能会进行flush操作。 * 1)执行HQL或QBC查询,会先进行flush操作,以得到数据表的最新的记录 * 2)若记录的ID是由底层数据库使用自增的方式生成的,则在调用save()方 * 法后会立即发送insert()语句,因为save()方法后,必须保证对象的 * ID是存在的 */ @Test public void testSessionFlush() { News news = (News)session.get(News.class, 1); news.setAuthor("Oracle"); // commit之前会调用flush() News news2 = (News) session.createCriteria(News.class).uniqueResult(); System.out.println(news2); } @Test public void testSessionFlush2() { News news = new News("Java", "SUN", new Date(new java.util.Date().getTime())); session.save(news); } /** * refresh会强制发送SELECT语句,以使SESSION缓存中对象的状态和数据表中对 * 应的记录保持一致!
   * 关于clear方法,可以查看下面的文章:
   * https://www.cnblogs.com/L-a-u-r-a/p/7049666.html 
*/ @Test public void testRefresh() { News news = (News)session.get(News.class, 1); System.out.println(news); // session.refresh(news); session.clear(); News news2 = (News)session.get(News.class, 1); System.out.println(news2); } /** * 对象的四种状态 */ /** * 1.save()方法 * 1)使一个临时对象变为持久化对象 * 2)为对象分配ID * 3)在flush缓存时会发送一条INSERT语句 * 4)在save方法之前的id是无效的 * 5)持久化对象的ID是不能被修改的 */ @Test public void testSave() { News news = new News(); news.setTitle("CC"); news.setAuthor("cc"); news.setDate(new Date(new java.util.Date().getTime())); // news.setId(100); System.out.println(news); session.save(news); // news.setId(200); System.out.println(news); } /** * persist():也会执行INSERT操作 * 和save()的区别: * 在调用persist方法之前,若对象已经有id了,则不会执行insert,而相反的,会抛出一个 * 异常 */ @Test public void testPersist() { News news = new News(); news.setTitle("EE"); news.setAuthor("dd"); news.setDate(new Date(new java.util.Date().getTime())); news.setId(200); session.persist(news); } /** * 1. 执行 get 方法会立即加载对象, * 而执行 load 方法,若不使用该对象,则不会立即执行查询操作,而返回一个代理对象。 * get 是立即检索,load 是延迟检索 * 2. 若数据库中没有对应的记录,Session也没有被关闭 * get 返回null * load 若不使用该对象的任何属性,没问题;若需要初始化了,抛出异常 * 3. load方法可能会抛出LazyInitializationException异常:在需要初始化代理对象之前已经关闭了session */ @Test public void testLoad() { News news = (News)session.load(News.class, 10); System.out.println(news.getClass().getName()); session.close(); System.out.println(news); } @Test public void testGet() { News news = (News)session.get(News.class, 1); session.close(); System.out.println(news); } /** * update: * 1. 若更新一个持久化对象,不需要显示的调用update方法,因为在调用 * transaction的commit方法时,会先执行session的flush方法 * 2. 更新一个游离对象,需要显示的调用session的update方法,可以把 * 一个游离对象变为持久化对象。
   * hibernate对象的四种状态:
   * https://www.cnblogs.com/cat36/p/5553232.html * 需要注意的: * 1. 无论要更新的游离对象和数据表的记录是否一致,都会发送update语句 * 如何能让update方法不再盲目的触发update语句呢?在.hbm.xml文件 * class节点设置一个属性,叫select-before-update为true,但通常不用 * 设置该属性 * 2. 若数据表中没有对应的记录,但还调用了update方法,会抛出异常 * 3. 当update方法关联一个游离对象时,如果在session的缓存中已经存在相同的OID持久化对象,会抛出异常,因为在session缓存中不能有两 * 个OID相同的对象
*/ @Test public void testUpdate() { News news = (News)session.get(News.class, 1); transaction.commit(); session.close(); // news.setId(300); session = sessionFactory.openSession(); transaction = session.beginTransaction(); // news.setAuthor("SUN"); News news2 = (News)session.get(News.class, 1); session.update(news); } /** * 注意: * 1. 若OID不为null, 但数据表中没有相应记录,会抛出异常 * 2. 了解:OID值等于id的unsaved-value属性值的对象,也认为是一个游离对象 */ @Test public void testSaveOrUpdate() { News news = new News("FF", "ff", new Date(1111111111111L)); news.setId(11); session.saveOrUpdate(news); } /** * delete:执行删除操作。只要OID和数据表中的一条记录对应,就会准备执行delete操作,若OID在 * 数据表中没有对应的记录,则抛出异常 * 可以通过设置hibernate配置文件的hibernate.use_identifier_rollback属性,使执行删除后的对象的id为null */ @Test public void testDelete() { // News news = new News(); // news.setId(1); News news = (News) session.get(News.class, 2); session.delete(news); System.out.println(news); } /** * evict: 从session缓存中把指定的持久化对象移除 */ @Test public void testEvict() { News news1 = (News)session.get(News.class, 1); News news2 = (News)session.get(News.class, 2); news1.setTitle("AA"); news2.setTitle("BB"); session.evict(news1); }
  /**
  * 进行批处理
  */ @Test
public void testDoWork() { session.doWork(new Work() { @Override public void execute(Connection arg0) throws SQLException { System.out.println(arg0); // 调用存储过程 } }); }
  /**
  * 动态更新,参看下面的文章:
  * http://blog.csdn.net/tctctttccc/article/details/76785199
  */ @Test
public void testDynamicUpdate() { News news = (News) session.get(News.class, 1); news.setAuthor("ABCD"); }
  /**
  * 主键id生成策略
  * http://ryxxlong.iteye.com/blog/612446
  */ @Test
public void testIdGenerator() throws InterruptedException { News news = new News("AA", "aa", new Date(22222222222222L)); session.save(news); Thread.sleep(5000); }
  /**
  * 属性更新或插入,参见下面的文章:
  * http://blog.csdn.net/lengxingxing_/article/details/68925879
  */ @Test
public void testPropertyUpdate() { News news = (News) session.get(News.class, 1); news.setAuthor("AAA"); news.setTitle("aaaaa"); System.out.println(news.getDesc()); System.out.println(news.getDate()); }
  /**
  * 二进制大数据的处理
  */ @Test
public void testBlob() throws Exception { // News news = new News(); // news.setAuthor("cc"); // news.setContent("CONTENT"); // news.setDate(new Date(11111111111L)); // news.setDesc("DESC"); // news.setTitle("CC"); // // InputStream stream = new FileInputStream(this.getClass().getResource("/").getPath() + "/jvhua.jpg"); // Blob image = Hibernate.getLobCreator(session) // .createBlob(stream, stream.available()); // news.setImage(image); // session.save(news); News news2 = (News)session.get(News.class, 1); Blob image2 = news2.getImage(); InputStream inputStream = image2.getBinaryStream(); System.out.println(inputStream.available()); }
  /**
  * Component的相关使用:
  * http://blog.csdn.net/itzyjr/article/details/8505789
  * http://fehly.iteye.com/blog/636409
  */ @Test
public void testComponent() { Worker worker = new Worker(); Pay pay = new Pay(); pay.setMonthlyPay(1000); pay.setYearlyPay(50000); pay.setVocationWithPay(55); worker.setName("abcd"); worker.setPay(pay); // session.save(worker); Worker worker2 = (Worker)session.get(Worker.class, 1); System.out.println("parent work name: " + worker2.getPay().getWorker().getName()); } }

  相应的映射文件:

  Work.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-22 11:36:52 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.helloworld">
    <class name="Worker" table="WORKER">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <!-- 映射组成关系 -->
        <component name="pay" class="Pay">
            <parent name="worker"/>
            <!-- 指定组成关系的组件的属性 -->
            <property name="monthlyPay" column="MONTHLY_PAY"></property>
            <property name="yearlyPay" column="YEARLY_PAY"></property>
            <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property>
            
        </component>
    </class>
</hibernate-mapping>

  有一个component

  News.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-17 12:21:26 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.helloworld">
  <!-- 动态插入,动态更新,更新前先选择 -->
<class name="News" table="NEWS" dynamic-insert="true" dynamic-update="true" select-before-update="false"> <id name="id" type="java.lang.Integer" unsaved-value="11"> <column name="ID" /> <!-- 指定主键的生成方式,native:使用数据库本地的方式 increment hilo sequence identity --> <generator class="native" /> </id>
    
    <!-- 唯一性,不可更新 -->
<property name="title" type="java.lang.String" unique="true" update="false" index="news_index"> <column name="TITLE" length="10" /> </property> <property name="author" type="java.lang.String" index="news_index"> <column name="AUTHOR" /> </property> <property name="date" type="date"> <column name="DATE" /> </property> <!-- 映射派生属性 --> <property name="desc" formula="(SELECT concat(author, ': ', title) FROM NEWS N WHERE n.id = id)"></property>
    <!-- 大文本 --> <property name="content"> <column name="CONTENT" sql-type="mediumtext"></column> </property>
    <!-- 二进制图片 --> <property name="image" type="blob"> <column name="IMAGE" sql-type="mediumblob"></column> </property> </class> </hibernate-mapping>

  有不少新东西,可以看一下

  内容太多了,就先讲到这里吧,其它的放到下一篇中继续说。

转载于:https://www.cnblogs.com/liunianfeiyu/p/8495142.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值