Hibernate框架的应用背景:

使用JDBC做数据库相关功能开发会做很多重复性的工作,比如创建连接,关闭连接,把字段逐一映射到属性中。 Hibernate把这一切都封装起来了,使得数据库访问变得轻松而简单,代码也更加容易维护。

HelloWorld基础:

  1. 准备好数据库和创建好数据表。
  2. 创建一个java project
  3. 导入相关的依赖jar包(hibernate不同版本之间的jar包存在兼容性问题,所以要保证版本一致性和兼容性)也可以自行从官网上下载最新版本。hibernate.rar :http://download.how2j.cn/308/hibernate.rar     lib.rar:http://download.how2j.cn/57/lib.rar
  4. 导包步骤: 右键project->property->java build path->libaries->add external jars 
  5. 创建实体类
    public class Product {
        int id;
        String name;
        float price;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public float getPrice() {
            return price;
        }
        public void setPrice(float price) {
            this.price = price;
        }
          
    }
  6. 创建和配置实体类对应的映射文件Product.hbm.xml,推荐将实体和映射文件放到同一个包下,便于管理,文件名 Product.hbm.xml  P一定要大写,要和类保持一致
    <?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.how2java.pojo"> 
        <class name="Product" table="product_">
            <id name="id" column="id">
                <generator class="native">
                </generator>
            </id>
            <property name="name" />
            <property name="price" />
        </class>
         
    </hibernate-mapping>
  7. 创建和配置Hibernate框架的配置文件,在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>
            <!-- Database connection settings -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8</property>
            <property name="connection.username">root</property>
            <property name="connection.password">admin</property>
            <!-- SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="current_session_context_class">thread</property>
            <property name="show_sql">true</property>
            <property name="hbm2ddl.auto">update</property>
            <!--实体类映射文件的导入-->
            <mapping resource="com/how2java/pojo/Product.hbm.xml" />
        </session-factory>
     
    </hibernate-configuration>
  8. 测试类TestHibernate
    public class TestHibernate {
        public static void main(String[] args) {
            // 1.获取SessionFactory 
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
     
            // 2.获取一个Session
            Session s = sf.openSession();
            // 3.开启一个事务
            s.beginTransaction();
     
            Product p = new Product();
            p.setName("iphone7");
            p.setPrice(7000);
            s.save(p);
            
            // 4.提交事务 
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
     
    }

通过api对数据库进行增删改查操作

实例类对象在Hibernate中有三种状态:
  • 瞬时 指的是没有和hibernate发生任何关系,在数据库中也没有对应的记录,一旦JVM结束,这个对象也就消失了 
  • 持久:指得是一个对象和hibernate发生联系,有对应的session,并且在数据库中有对应的一条记录 
  • 脱管 指的是一个对象虽然在数据库中有对应的一条记录,但是它所对应的session已经关闭了 

通过ID获取一个对象:

调用Session的get方法,根据id获取对象。 除了id之外,还需要传递一个类对象,毕竟需要知道获取的是哪个对象。
还可以通过load方式,两者的区别是
  • load方法是延迟加载,只有属性被访问的时候才会调用sql语句。如果对象不存在抛出异常。
  • get方法是非延迟加载,无论后面的代买是否会被访问到属性,马上执行sql语句。如果对象不存在返回null。
public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
  
        Session s = sf.openSession();
        s.beginTransaction();
  
        Product p =(Product) s.get(Product.class, 6);   // 获取一个对象,ID为6
          
        System.out.println("id=6的产品名称是: "+p.getName());
          
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
  
}

通过获取对象后,删除一个对象:
 public class TestHibernate {
    public static void main(String[] args) {
 
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
 
        Product p =(Product) s.get(Product.class, 5);   //1.先获取对象
        s.delete(p);    //2.再删除对象
         
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
 
}

修改一个对象的属性:

public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
 
        Product p =(Product) s.get(Product.class, 6);  //1.先获取对象
         
        System.out.println(p.getName());
         
        p.setName("iphone-modified");   //2.对获取的对象进行修改属性
         
        s.update(p);         //3.更新修改后的对象
         
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
 
}

查询对象:

使用HQL,根据name进行模糊查询。(使用hql用的类名Product,而不是表名。不需要在前面加select)
  1. 首先根据hql创建一个Query对象
  2. 设置参数(以0为基准,PreparedStatement是以1开始)
  3. 通过Query对象的list()方法返回查询的结果。
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
     
            Session s = sf.openSession();
            s.beginTransaction();
     
            String name = "iphone";
            Query q =s.createQuery("from Product p where p.name like ?");
            q.setString(0, "%"+name+"%");
            List<Product> ps= q.list();
            for (Product p : ps) {
                System.out.println(p.getName());
            }
             
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
     
    }

使用Criteria 查询

  1. 通过session的createCriteria创建一个Criteria对象
  2. Criteria.add增加约束。
  3. 调用list()方法返回查询的结果
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
      
            Session s = sf.openSession();
            s.beginTransaction();
     
            String name = "iphone";
              
            Criteria c= s.createCriteria(Product.class);
            c.add(Restrictions.like("name", "%"+name+"%"));
            List<Product> ps = c.list();
            for (Product p : ps) {
                System.out.println(p.getName());
            }
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }

  1. 使用Criteria进行分页查询 

  • Hibernate使用Criteria 来进行分页查询
  • c.setFirstResult(2); 表示从第3条数据开始
  • c.setMaxResults(5); 表示一共查询5条数据
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
      
            Session s = sf.openSession();
            s.beginTransaction();
      
            String name = "iphone";
              
            Criteria c= s.createCriteria(Product.class);
            c.add(Restrictions.like("name", "%"+name+"%"));
            c.setFirstResult(2);
            c.setMaxResults(5);
             
            List<Product> ps = c.list();
            for (Product p : ps) {
                System.out.println(p.getName());
                 
            }
              
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }
    查询总数
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
            Session s = sf.openSession();
            s.beginTransaction();
      
            String name = "iphone";
             
            Query q =s.createQuery("select count(*) from Product p where p.name like ?");
            q.setString(0, "%"+name+"%");
            long total= (Long) q.uniqueResult();
            System.out.println(total);
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
      
    }
使用标准的sql查询:
public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
 
        String name = "iphone";
         
        String sql = "select * from product_ p where p.name like '%"+name+"%'";
         
        Query q= s.createSQLQuery(sql);
        List<Object[]> list= q.list();
        for (Object[] os : list) {
            for (Object filed: os) {
                System.out.print(filed+"\t");
            }
            System.out.println();
        }
         
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
}

Hibernate之间的实体关系:

多对一

  1. 除了product产品类,再加一个Category种类的实体(其实体类和映射文件Category.hbm.xml)类似于Product类。一个产品对应一个种类,一个种类对应多个产品
  2. 在Product类中增加Category属性,在Product.hbm.xml对应的映射文件中
    <hibernate-mapping package="com.how2java.pojo">
        <class name="Product" table="product_">
            <id name="id" column="id">
                <generator class="native">
                </generator>
            </id>
     
            <property name="name" />
            <property name="price" />
            <many-to-one name="category" class="Category" column="cid" />
        </class>
         
    </hibernate-mapping>
  3. 在hibernate.cfg.xml中增加Category的映射<mapping resource="com/how2java/pojo/Category.hbm.xml" />
  4. 通过代码测试:
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
      
            Session s = sf.openSession();
            s.beginTransaction();
             
            Category c =new Category();
            c.setName("c1");
            s.save(c);
             
            Product p = (Product) s.get(Product.class, 8);
            p.setCategory(c);
            s.update(p);
             
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }

一对多

  1. 为Category类增加一个Set集合
  2. 为Category.hbm.xml增加one-to-many映射
    <set name="products" lazy="false">
         <key column="cid" not-null="false" />
         <one-to-many class="Product" />
    </set>
  3. 测试
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
      
            Session s = sf.openSession();
            s.beginTransaction();
             
            Category c = (Category) s.get(Category.class, 1);
            Set<Product> ps = c.getProducts();
            for (Product p : ps) {
                System.out.println(p.getName());
            }
     
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }

多对多

用户和产品之间的关系。
  1. 增加User.java实体类   
     
    public class User {
     
        int id;
        String name;
        Set<Product> products;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Set<Product> getProducts() {
            return products;
        }
        public void setProducts(Set<Product> products) {
            this.products = products;
        }
    } 
  2. User.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.how2java.pojo">
        <class name="User" table="user_">
            <id name="id" column="id">
                <generator class="native">
                </generator>
            </id>
            <property name="name" />
     
            <set name="products" table="user_product" lazy="false">
                <key column="uid" />
                <many-to-many column="pid" class="Product" />
            </set>       
             
        </class>
         
    </hibernate-mapping> 
  3. Product.java  实体类  
     
    public class Product {
        int id;
        String name;
        float price;
        Category category;
        Set<User> users;
     
        public Set<User> getUsers() {
            return users;
        }
        public void setUsers(Set<User> users) {
            this.users = users;
        }
        public Category getCategory() {
            return category;
        }
        public void setCategory(Category category) {
            this.category = category;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public float getPrice() {
            return price;
        }
        public void setPrice(float price) {
            this.price = price;
        }
         
    }
  4. Product.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.how2java.pojo">
        <class name="Product" table="product_">
            <id name="id" column="id">
                <generator class="native">
                </generator>
            </id>
            <property name="name" />
            <property name="price" />
            <many-to-one name="category" class="Category" column="cid" />
             
            <set name="users" table="user_product" lazy="false">
                <key column="pid" />
                <many-to-many column="uid" class="User" />
            </set>       
                     
        </class>
         
    </hibernate-mapping>
  5. 在hibernate.cfg.xml中增加User的映射 
    <?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>
            <!-- Database connection settings -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=GBK</property>
            <property name="connection.username">root</property>
            <property name="connection.password">admin</property>
            <!-- SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="current_session_context_class">thread</property>
            <property name="show_sql">true</property>
            <property name="hbm2ddl.auto">update</property>
            <mapping resource="com/how2java/pojo/Product.hbm.xml" />
            <mapping resource="com/how2java/pojo/Category.hbm.xml" />
            <mapping resource="com/how2java/pojo/User.hbm.xml" />
        </session-factory>
     
    </hibernate-configuration>  
  6. TestHibernate 测试many-to-many关系
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
       
            Session s = sf.openSession();
            s.beginTransaction();
              
            //增加3个用户
            Set<User> users = new HashSet();
            for (int i = 0; i < 3; i++) {
                User u =new User();
                u.setName("user"+i);
                users.add(u);
                s.save(u);
            }
              
            //产品1被用户1,2,3购买
            Product p1 = (Product) s.get(Product.class, 1);
              
            p1.setUsers(users);
            s.save(p1);
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }

级联:如果配置了级联,删除分类的时候,对应的产品也都会被删除掉。

  1. all:所有操作都执行的级联操作
  2. none:所有操作都不执行级联操作
  3. delete:删除时执行级联操作
  4. save-update:保存和更新时执行级联操作
级联通常在one-to-many和many-to-many上,几乎不用在many-one上。

例如:
  1. 在一对多的基础上,修改test类中
    Category c = (Category) s.get(Category.class, 3);
    s.delete(c);   //删除一的一方
  2. 在对应的Category.hbm.xml中 cascade
    <set name="products" cascade="delete" lazy="false">
    运行代码就会发现,删除分类的时候,会把分类下对应的产品都删除掉,否则只会把产品对应的cid设置为空

一级缓存:

hibernate默认是开启一级缓存的,一级缓存存放在session上。
  • 第一次通过id=1获取对象的时候,session中是没有对应缓存对象的,所以会在"log1"后出现sql查询语句。
  • 第二次通过id=1获取对象的时候,session中有对应的缓存对象,所以在"log2"后不会出现sql查询语句

二级缓存:

二级缓存是在SessionFactory上创建了两个Session
在第一个Session里
  • 第一次获取id=1的Category 执行SQL语句
  • 第二次获取id=1的Category,不会执行SQL语句,因为有一级缓存
在第二个Session里
  • 获取id=1的Category,执行SQL语句,因为在第二个Session,没有缓存该对象。 
  • 所以总共会看到两条SQL语句。
在hibernate.cfg.xml中开启二级缓存的配置。hibernate本身不提供二级缓存,都是使用第三方的二级缓存插件。这里使用的是 EhCache提供的二级缓存
    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>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=GBK</property>
        <property name="connection.username">root</property>
        <property name="connection.password">admin</property>
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="current_session_context_class">thread</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
         
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
          
        <mapping resource="com/how2java/pojo/Product.hbm.xml" />
        <mapping resource="com/how2java/pojo/Category.hbm.xml" />
        <mapping resource="com/how2java/pojo/User.hbm.xml" />
         
    </session-factory>
 
</hibernate-configuration>
在src目录下,创建一个ehcache.xml用于EHCache的缓存配置
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
</ehcache>
对于要进行二级缓存的实体类映射文件进行配置。
<?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.how2java.pojo">
    <class name="Category" table="category_">
        <cache usage="read-only" />
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <property name="name" />
 
        <set name="products" lazy="true">
            <key column="cid" not-null="false" />
            <one-to-many class="Product" />
        </set>
                 
    </class>
     
</hibernate-mapping>

Hibernate有两种获取session的方式:

openSessiongetCurrentSession 

1. 获取的是否是同一个session对象 

openSession每次都会得到一个新的Session对象 
getCurrentSession在同一个线程中,每次都是获取相同的Session对象,但是在不同的线程中获取的是不同的Session对象 

2. 事务提交的必要性 

openSession只有在增加,删除,修改的时候需要事务,查询时不需要的 
getCurrentSession是所有操作都必须放在事务中进行,并且提交事务后,session就自动关闭,不能够再进行关闭

Hibernate N+1:

Hibernate有缓存机制,可以通过用id作为key把product对象保存在缓存中 
同时hibernate也提供Query的查询方式。假设数据库中有100条记录,其中有30条记录在缓存中,但是使用Query的list方法,就会所有的100条数据都从数据库中查询,而无视这30条缓存中的记录 
而N+1,首先执行一条sql语句,去查询这100条记录,但是,只返回这100条记录的ID然后再根据id,进行进一步查询。
如果id在缓存中,就从缓存中获取,否则再取数据库。
N+1中的1,就是指只返回id的SQL语句,N指的是如果在缓存中找不到对应的数据,就到数据库中去查

Hibernate使用乐观锁处理脏数据问题:

    1. 通过session1得到id=1的对象 product1
    2. 在product1原来价格的基础上增加1000
    3. 更新product1之前,通过session2得到id=1的对象product2
    4. 在product2原来价格的基础上增加1000
    5. 更新product1
    6. 更新product2

结果只增加了1000


修改配置文件 Product.hbm.xml   增加一个version字段,用于版本信息控制。这就是乐观锁的核心机制。
比如session1获取product1的时候,version=1。 那么session1更新product1的时候,就需要确保version还是1才可以进行更新,并且更新结束后,把version改为2。
<?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.how2java.pojo">
    <class name="Product" table="product_">
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <!--version元素必须紧挨着id后面  -->
        <version name="version" column="ver" type="int"></version>
        <property name="name" />
        <property name="price" />
 
        <many-to-one name="category" class="Category" column="cid" />
 
        <set name="users" table="user_product" lazy="false">
            <key column="pid" />
            <many-to-many column="uid" class="User" />
        </set>
 
    </class>
 
</hibernate-mapping>
修改 Product.java实体类,增加int version作为属性

数据库连接池:

建立数据库连接时比较消耗时间的,所以通常都会采用数据库连接池的技术来建立多条数据库连接,并且在将来持续使用,从而节约掉建立数据库连接的时间 
hibernate本身是提供了数据库连接池的,但是hibernate官网也不推荐使用他自带的数据库连接池。 
一般都会使用第三方的数据库连接池 
C3P0是免费的第三方的数据库连接池,并且有不错的表现 
右边可以下载c3p0的jar包  只有在高并发量的情况下,才会体会数据库连接池的优越。
  1. 下载导入c3p0jar包
  2. 进行c3p0配置
    <?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>
            <!-- Database connection settings -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=GBK</property>
            <property name="connection.username">root</property>
            <property name="connection.password">admin</property>
            <!-- SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="current_session_context_class">thread</property>
            <property name="show_sql">true</property>
            <property name="hbm2ddl.auto">update</property>
              
            <property name="hibernate.connection.provider_class"> 
                org.hibernate.connection.C3P0ConnectionProvider 
            </property> 
            <property name="hibernate.c3p0.max_size">20</property> 
            <property name="hibernate.c3p0.min_size">5</property> 
            <property name="hibernate.c3p0.timeout">50000</property> 
            <property name="hibernate.c3p0.max_statements">100</property> 
            <property name="hibernate.c3p0.idle_test_period">3000</property> 
            <!-- 当连接池耗尽并接到获得连接的请求,则新增加连接的数量 -->
            <property name="hibernate.c3p0.acquire_increment">2</property> 
            <!-- 是否验证,检查连接 -->
            <property name="hibernate.c3p0.validate">false</property>           
              
            <mapping resource="com/how2java/pojo/Product.hbm.xml" />
            <mapping resource="com/how2java/pojo/Category.hbm.xml" />
            <mapping resource="com/how2java/pojo/User.hbm.xml" />
              
        </session-factory>
      
    </hibernate-configuration>
  3. 去掉实体类映射文件中的二级缓存<cache usage="read-only" />
  4. 测试类
    public class TestHibernate {
        public static void main(String[] args) {
            SessionFactory sf = new Configuration().configure().buildSessionFactory();
       
            Session s = sf.openSession();
            s.beginTransaction();
       
            s.createQuery("from Category").list();
               
            s.getTransaction().commit();
            s.close();
            sf.close();
        }
    }

Hibernate注解:

本来放在hbm.xml文件里的映射信息,现在不用配置文件做了,改由注解来完成
使用注解的实体类
 
@Entity
@Table(name = "product_")
public class Product {
    int id;
    String name;
    float price;
     
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")  
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Column(name = "name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Column(name = "price")
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
      
}
hibernate.cfg.xml 配置文件改动
<mapping resource="com/how2java/pojo/Product.hbm.xml" />注释掉
增加<mapping class="com.how2java.pojo.Product" />

注解的相关解释:

类注解
  • @Entity 表示这是一个实体类,用于映射表
  • @Table(name = "product_") 表示这是一个类,映射到的表名:product_
    @Entity
    @Table(name = "product_")
    public class Product {
        int id;
        String name;
        float price;
    }
属性注解
  • @Id 表示这是主键
  • @GeneratedValue(strategy = GenerationType.IDENTITY) 表示自增长方式使用mysql自带的
  • @Column(name = "id") 表示映射到字段id
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY) 
        @Column(name = "id")   
        public int getId() {
            return id;
        }
    				
    @Column(name = "price")
    public float getPrice() {
    return price;
    }

多对一注解
@ManyToOne   表示多对一关系
@JoinColumn(name="cid")  表示关系字段是cid

一对多注解
@OneToMany(fetch=FetchType.EAGER)    fetch=FetchType.EAGER 表示不进行延迟加载(FetchType.LAZY表示要进行延迟加载)
@JoinColumn(name="cid")

多对多注解
ManyToMany
为Product的getUsers加上
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinTable(
name="user_product",
joinColumns=@JoinColumn(name="pid"),
inverseJoinColumns=@JoinColumn(name="uid")
)
public Set<User> getUsers() {
return users;
}

对比Product.hbm.xml中的配置:
<set name="users" table="user_product" lazy="false">
<key column="pid" />
<many-to-many column="uid" class="User" />
</set>

为User的getProducts加上
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinTable(
name="user_product",
joinColumns=@JoinColumn(name="uid"),
inverseJoinColumns=@JoinColumn(name="pid")
)
public Set<Product> getProducts() {
return products;
}

对比User.hbm.xml中的配置
<set name="products" table="user_product" lazy="false">
<key column="uid" />
<many-to-many column="pid" class="Product" />
</set>
6. hibernate.cfg.xml
<mapping class="com.how2java.pojo.Product" />
<mapping class="com.how2java.pojo.Category" />
<mapping class="com.how2java.pojo.User" />