zoukankan      html  css  js  c++  java
  • Hibernate

    从以下5个方面学习hibernate ORM。

    (1)配置文件:hibernate.cfg.xml XML文件和hibernate.properties属性文件

    (2)实体映射:1对多、多对多

    (3)会话工厂与会话:SessionFactory&Session

    (4)查询:SQL原生查询、HQL通用查询、Criteria条件查询

    (5)事务:Transanction

    Hibernate的5个核心对象Conifguration、SessionFactory、Session、Query和Transanction是必须掌握的。另外,没有类似Linq的语言集成查询。

    1.配置文件:hibernate.cfg.xml XML文件和hibernate.properties属性文件

    Hibernate使用Configuration表示配置信息,配置文件的信息最终会适配到Configuration对象。虽然XML文件一直被hibernate支持,但使用hibernate.properties属性文件更简洁。

    HSQLDB数据库是一个常用的JAVA版的测试数据库,我们通过下面两种方式演示HSQLDB数据库的配置。其中connection.driver_class, connection.url, connection.username 和 connection.password提供了JDBC使用的数据库链接信息,dialect配置SQL方言,hbm2ddl.auto配置启用自动更新数据库模式,show_sql和format_sql配置便于我们在控制台查看输出信息,generate_statistics配置生成统计信息。

    (1)XML方式配置Hibernate:

    复制代码
     1 <?xml version='1.0' encoding='utf-8'?>
     2 <!DOCTYPE hibernate-configuration PUBLIC
     3     "-//Hibernate/Hibernate Configuration DTD//EN"
     4     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     5 
     6 <hibernate-configuration>
     7     <session-factory>
     8         <property name="hibernate.connection.driver_class">org.h2.Driver</property>
     9         <property name="hibernate.connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
    10         <property name="hibernate.connection.username">sa</property>
    11         <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
    12         <property name="hibernate.hbm2ddl.auto">update</property>
    13         <property name="hibernate.show_sql">true</property>
    14         <property name="hibernate.format_sql">true</property>
    15         <property name="hibernate.generate_statistics">true</property>
    16     </session-factory>
    17 </hibernate-configuration>
    复制代码

    (2)属性文件方式配置Hibernate:

    复制代码
    1 hibernate.connection.driver_class org.h2.Driver
    2 hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
    3 hibernate.connection.username sa
    4 hibernate.dialect org.hibernate.dialect.H2Dialect
    5 hibernate.hbm2ddl.auto update
    6 hibernate.show_sql true
    7 hibernate.format_sql true
    8 hibernate.generate_statistics true
    复制代码

    2.实体映射:1对多、多对多

    Hibernate的实体映射可以采取XML和代码注解两种, .NET中的EntityFramework的实体映射也有对应的注解(特性)方式,但提供了让实体类更加干净的代码配置方式。无论是依赖注入还是实体映射,Spring和Hibernate在这方面始终相对落后和繁琐。

    各种JAVA框架的核心从来不是xml,框架的核心功能和核心对象才是最重要的。注解配置的核心注解如下:

    (1)@Entity:标注类为实体。

    (2)@Id和@GeneratedValue:前者标注POJO字段为主键,后者标注字段为数据库自动生成。

    (3)@OneToMany和@ManyToOne:在关联字段上标注1对多和多对1。

    (4)@ManyToMany:在关联字段上标注多对多,cascade参数指定级联处理规则。

    (5)@Version:标注字段为乐观并发控制版本字段。

    下面分别演示常见的1对多、多对多的映射配置。

    (1)1对多:Category-Post

    Category代码:

    复制代码
     1 @Entity
     2 public class Category {
     3 
     4     @Id
     5     @GeneratedValue
     6     private int id;
     7 
     8     private String Name;
     9 
    10     @OneToMany
    11     private List<Post> posts = new ArrayList<Post>();
    12 
    13     public int getId() {
    14         return id;
    15     }
    16 
    17     public void setId(int id) {
    18         this.id = id;
    19     }
    20 
    21     public String getName() {
    22         return Name;
    23     }
    24 
    25     public void setName(String name) {
    26         Name = name;
    27     }
    28 
    29     public List<Post> getPosts() {
    30         return posts;
    31     }
    32 
    33     public void setPosts(List<Post> posts) {
    34         this.posts = posts;
    35     }
    36 }
    复制代码

    Post代码:

    复制代码
    @Entity
    public class Post {
        @Id
        @GeneratedValue
        private int id;
    
        private String Name;
    
        private String Text;
    
        @ManyToOne
        private 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) {
            Name = name;
        }
    
        public String getText() {
            return Text;
        }
    
        public void setText(String text) {
            Text = text;
        }
    
        public Category getCategory() {
            return category;
        }
    
        public void setCategory(Category category) {
            this.category = category;
        }
    }
    复制代码

    (2)多对多+乐观锁:User-Role

    User代码:

    复制代码
     1 @Entity
     2 public class User {
     3     @Id
     4     @GeneratedValue
     5     private int id;
     6 
     7     private String userName;
     8 
     9     private String password;
    10 
    11     @Version
    12     private long version;
    13 
    14     @ManyToMany(cascade = CascadeType.ALL)
    15     private List<Role> roles = new ArrayList<Role>();
    16 
    17     public int getId() {
    18         return id;
    19     }
    20 
    21     public void setId(int id) {
    22         this.id = id;
    23     }
    24 
    25     public String getUserName() {
    26         return userName;
    27     }
    28 
    29     public void setUserName(String userName) {
    30         this.userName = userName;
    31     }
    32 
    33     public String getPassword() {
    34         return password;
    35     }
    36 
    37     public void setPassword(String password) {
    38         this.password = password;
    39     }
    40 
    41     public long getVersion() {
    42         return version;
    43     }
    44 
    45     public void setVersion(long version) {
    46         this.version = version;
    47     }
    48 
    49     public List<Role> getRoles() {
    50         return roles;
    51     }
    52 
    53     public void setRoles(List<Role> roles) {
    54         this.roles = roles;
    55     }
    56 
    57 }
    复制代码

    Role代码:

    复制代码
     1 @Entity
     2 public class Role {
     3     @Id
     4     @GeneratedValue
     5     private int id;
     6 
     7     private String roleName;
     8 
     9     @ManyToMany(cascade = CascadeType.ALL)
    10     private List<User> users = new ArrayList<User>();
    11 
    12     public int getId() {
    13         return id;
    14     }
    15 
    16     public void setId(int id) {
    17         this.id = id;
    18     }
    19 
    20     public String getRoleName() {
    21         return roleName;
    22     }
    23 
    24     public void setRoleName(String roleName) {
    25         this.roleName = roleName;
    26     }
    27 
    28     public List<User> getUsers() {
    29         return users;
    30     }
    31 
    32     public void setUsers(List<User> users) {
    33         this.users = users;
    34     }
    35 }
    复制代码

    3.会话工厂与会话:SessionFactory&Session

    (1)会话上下文SessionFactory

    SessionFactory始终是Hibernate的核心对象.通过Configuration创建的SessionFactory是Hibernate ORM的核心对象。Hibernate 4.3.5和Hibernate 5.x可以使用一致的代码创建SessionFactory,但5.x需要引入jta(javax.transaction),否则创建失败。

    复制代码
     1     public SessionFactory sessionFactory() {
     2 
     3         org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
     4 
     5         configuration.addAnnotatedClass(User.class);
     6         configuration.addAnnotatedClass(Role.class);
     7         configuration.addAnnotatedClass(Category.class);
     8         configuration.addAnnotatedClass(Post.class);
     9 
    10         SessionFactory sessionFactory = configuration.buildSessionFactory(new StandardServiceRegistryBuilder().build());
    11         return sessionFactory;
    12 
    13     }
    复制代码

    (2)会话Session

    Session对象类似于EntityFramework中DbContext对象。Hibernate中通过SessionFactory获取Session,有2种方式openSession()和 getCurrentSession()。openSession方式获取单个打开的Session,需要自己写代码关闭。getCurrentSession方式则可以获取自动管理的Session对象,这是依赖CurrentSessionContext接口的实现类来支持的,可以通过配置hibernate.current_session_context_class来适配,取值"jta","thread"和"managed"分别对应三个实现类。使用getCurrentSession时虽然不需要手动管理Session的关闭,但是需要手动管理Transaction事务的开启和关闭。在Spring中继承Hibernate时,Spring提供了CurrentSessionContext的实现类SpringJtaSessionContext,避免了我们手动管理事务。在不使用Spring的Servlet环境中,我们可以选择使用Filter+getSession方式使用Session。也可以配置成"thread"+手动管理事务方式。

    Filter+getSession可以直接使用click-extras程序包中的Filter和SessionContext,最好是复用并修改其源码,其中SessionContext的实现核心是使用类型为ThreadLocal<Session>的静态字段实现线程级别的Session共享。

    click-extras的pom如下:

    1 <dependency>
    2     <groupId>org.apache.click</groupId>
    3     <artifactId>click-extras</artifactId>
    4     <version>2.3.0</version>
    5 </dependency>

    使用"thread"+手动管理事务方式需要先配置hibernate.properties属性文件:hibernate.current_session_context_class thread。

    复制代码
    1     private void Test(SessionFactory factory)
    2     {
    3         factory.getCurrentSession().beginTransaction();
    4         Query query = factory.getCurrentSession().createSQLQuery("select * from User where userName=?").addEntity(User.class);
    5         User user = (User) query.uniqueResult();
    6         factory.getCurrentSession().getTransaction().commit();
    7     }
    复制代码

    4.查询:SQL原生查询、HQL通用查询、Criteria条件查询

    (1)SQL原生查询:

    原生查询使用Query接口的子接口SQLQuery。通过session可以创建该接口的实例。下面的代码中hsqldb的参数化查询占位符是"?"。为了便于使用,使用了SQLQuery的addEntity方法配置查询对应的实体类型。

    1     private User SqlQuery() {
    2         Session session = SessionContext.getSession();
    3         Query query = session.createSQLQuery("select * from User where userName=?").addEntity(User.class);
    4         query.setString(0, "admin");
    5         return (User) query.uniqueResult();
    6     }

    (2)HQL通用查询:

    Hibernate使用Query接口,通过自定义的HQL实现通用查询,HQL提供了一个中间语言,屏蔽了不同数据库的语法差异。通过session可以创建Query接口的实例。

    1     private User SqlQuery() {
    2         Session session = SessionContext.getSession();
    3         Query query = session.createQuery("from User where userName=:userName");
    4         query.setString("userName", "admin");
    5         return (User) query.uniqueResult();
    6     }

    (3)Criteria条件查询:

    Hibernate通过Criteria对象提供对自动化查询的方法级别的支持,辅助类Restrictions提供了大量静态方法创建Criteria对象,最大的作用就是防止写错SQL关键字。Java中没有类似.NET中Linq一样的语言集成查询。

    1     private User CriteriaQuery() {
    2         Session session = SessionContext.getSession();
    3         Criteria query = session.createCriteria(User.class);
    4         query.add(Restrictions.eq("userName", "admin"));
    5         return (User) query.uniqueResult();
    6     }

    5.事务

     Transanction接口是Hibernate中封装事务的接口,支持JDBC数据库事务和JTA分布式事务,可以通过Session对象使用Transanction进行事务管理。JAT事务则与JTA容器紧密相关,以后再续。

    复制代码
    1     private void Test(SessionFactory factory) {
    2         factory.getCurrentSession().beginTransaction();
    3         Query query = factory.getCurrentSession().createSQLQuery("select * from User where userName=?")
    4                 .addEntity(User.class);
    5         User user = (User) query.uniqueResult();
    6         factory.getCurrentSession().getTransaction().commit();
    7     } 
    复制代码
  • 相关阅读:
    hdu 5366 简单递推
    hdu 5365 判断正方形
    hdu 3635 并查集
    hdu 4497 数论
    hdu5419 Victor and Toys
    hdu5426 Rikka with Game
    poj2074 Line of Sight
    hdu5425 Rikka with Tree II
    hdu5424 Rikka with Graph II
    poj1009 Edge Detection
  • 原文地址:https://www.cnblogs.com/gy19920604/p/5217037.html
Copyright © 2011-2022 走看看