Hibernate POJO类和数据库的映射文件 *.hbm.xml

1. 映射文件概述:

  • POJO类和关系数据库之间的映射可以用一个XML文档来定义
  • 通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据表之间的对应关系
  • 在运行时Hibernate将根据这个映射文件来生成各种SQL语句
  • 映射文件的扩展名为.hbm.xml
  • 在一个映射文件里面可以定义多个<class> </class>子节点,但是我们通常建议一个类配置一个映射文件

 

2.  生成主键的方式有哪些,各有什么优缺点:

  • increment:

 

  • identity

  •  sequence

 

  • hilo

  • native

 

3. 属性类型 与 Hibernate 类型以及 数据库类型 之间的映射关系

 

 

 

4. property

 

 

  • unique="true"(唯一的,可以做为索引) update="false"(不可以更改的) index="news_index"(把TITLE列设置一个索引值) length="20"(设置字段的长度)

<property name="title" type="string" 
    column="TITLE" unique="true"(唯一的,可以做为索引) update="false"(不可以更改的) index="news_index"(把TITLE列设置一个索引值) length="20"(设置字段的长度)>
</property>

<property name="author" type="java.lang.String" index="news_index“(把AUTHOR列设置一个索引值)
    <column name="AUTHOR" />
</property>

 

利用上面的设置的属性,可以得到如下的数据表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<hibernate-mapping>
     < class  name= "hibernate.sessiondemo.News"  table= "NEWS" >
         <id name= "id"  type= "java.lang.Integer" >
             <column name= "ID"  />
             <generator  class = "native"  />
         </id>
         <property name= "title"  type= "string"  column= "TITLE"  unique= "true"  update= "false"  index= "news_index"  length= "20" >
         </property>
         <property name= "author"  type= "java.lang.String"  index= "news_index" >
             <column name= "AUTHOR"  />
         </property>
         <property name= "date"  type= "java.util.Date" >
             <column name= "DATE"  />
         </property>
     </ class >
</hibernate-mapping>

 

 

  • formula:
    • formula="(sql)" 的英文括号不能少
    • sql表达式中的列名和表名都应该和数据库对应,而不是和持久化对象的属性对应
    • 如果需要在formula属性中使用参数,则直接使用WHERE cur.id=id 的形式, 其中id就是 和当前持久化对象的id属性对应的列 的id值将作为参数传入。

<!-- 映射派生属性 -->
<property name="desc" formula="(SELECT concat(author, ':', title) FROM NEWS n WHERE n.id=id)"
</property>

复制代码
<hibernate-mapping>
    <class name="hibernate.sessiondemo.News" table="NEWS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="title" type="string" column="TITLE" unique="true" update="false" index="news_index" length="20">
        </property>
        <property name="author" type="java.lang.String" index="news_index">
            <column name="AUTHOR" />
        </property>
        <property name="date" type="java.util.Date">
            <column name="DATE" />
        </property>
        
        <!-- 映射派生属性 -->
        <property name="desc" formula="(SELECT concat(author, ':', title) FROM NEWS n WHERE n.id=id)"> 
        </property>
    </class>
</hibernate-mapping>
复制代码

 

 

  • 映射JAVA的时间 日期属性
    • 两个基础知识:
      • 在JAVA中,代表时间和日期的类包括: java.util.Date 和 java.util.Calendar.  此外,在JDBC API还提供了3个扩展了java.util.Date 类的子类 java.sql.Date, java.sql.Time和java.sql.Timestamp, 这三个类分别和标准SQL的 DATE  TIME和TIMESTAMP 类型对应。
      • 在标准的SQL 中, DATE表示日期, TIME表示时间, TIMESTAMP表示时间戳。
    • 如何进行映射:
      •  java.util.Date是java.sql.Date, java.sql.Time和java.sql.Timestamp 的父类, 所以java.util.Date 可以和这三种类型对应 (在标准的SQL 中, DATE表示日期, TIME表示时间)
      •  在设置持久化类的类型时,设置为java.util.Date, 因为这个累心可以和上面三个都兼容
      • 那么如何把 java.util.Date 映射为 DATE表示日期, TIME表示时间,TIMESTAMP时间戳。

<property name="date" type="timestamp">
    <column name="DATE" />
</property>

<property name="date" type="time">
    <column name="DATE" />
</property>

<property name="date" type="date">
    <column name="DATE" />
</property>

 

 

  • component属性设置:具体实现参照代码

 

 

work的持久化类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package  hibernate.sessiondemo;
 
public  class  Worker {
     private  Integer id;
     private  String name;
     
     private  Pay pay;
 
     public  Integer getId() {
         return  id;
     }
 
     public  void  setId(Integer id) {
         this .id = id;
     }
 
     public  String getName() {
         return  name;
     }
 
     public  void  setName(String name) {
         this .name = name;
     }
 
     public  Pay getPay() {
         return  pay;
     }
 
     public  void  setPay(Pay pay) {
         this .pay = pay;
     }
}

 

pay的持久化类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package  hibernate.sessiondemo;
 
public  class  Pay {
     private  int  monthlyPay;
     private  int  yearPay;
     private  int  vocationWithPay;
 
     public  int  getMonthlyPay() {
         return  monthlyPay;
     }
 
     public  void  setMonthlyPay( int  monthlyPay) {
         this .monthlyPay = monthlyPay;
     }
 
     public  int  getYearPay() {
         return  yearPay;
     }
 
     public  void  setYearPay( int  yearPay) {
         this .yearPay = yearPay;
     }
 
     public  int  getVocationWithPay() {
         return  vocationWithPay;
     }
 
     public  void  setVocationWithPay( int  vocationWithPay) {
         this .vocationWithPay = vocationWithPay;
     }
}

配置文件, 主要关注: componentshuxing  

复制代码
<?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 Feb 20, 2016 4:22:33 PM by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.sessiondemo">
    <class name="Worker" table="WORKER">
        <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>
        
        <!-- 映射组成关系 -->
        <component name="pay">
            <!-- 指定组成关系的组件的属性 -->
            <property name="monthlyPay" column="MONTHLY_PAY"></property>
            <property name="yearPay" column="YEAR_PAY"></property>
            <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property>
        </component>
    </class>
</hibernate-mapping>
复制代码

 生成的数据表:

 

 

最后贴上以上所有例子的代码:

News.java

复制代码
package hibernate.sessiondemo;

import java.util.Date;

public class News {
    
    private Integer id;
    private String title;
    private String author;
    
    private Date date;
    
    private String desc;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
    
    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public News(String title, String author, Date date) {
        super();
        this.title = title;
        this.author = author;
        this.date = date;
    }

    public News() {
        super();
        // TODO Auto-generated constructor stub
    }

    @Override
    public String toString() {
        return "News [id=" + id + ", title=" + title + ", author=" + author + ", date=" + date + "]";
    }
}
复制代码

Worker.java

复制代码
package hibernate.sessiondemo;

public class Worker {
    private Integer id;
    private String name;
    
    private Pay pay;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Pay getPay() {
        return pay;
    }

    public void setPay(Pay pay) {
        this.pay = pay;
    }
}
复制代码

Pay.java

复制代码
package hibernate.sessiondemo;

public class Pay {
    private int monthlyPay;
    private int yearPay;
    private int vocationWithPay;

    public int getMonthlyPay() {
        return monthlyPay;
    }

    public void setMonthlyPay(int monthlyPay) {
        this.monthlyPay = monthlyPay;
    }

    public int getYearPay() {
        return yearPay;
    }

    public void setYearPay(int yearPay) {
        this.yearPay = yearPay;
    }

    public int getVocationWithPay() {
        return vocationWithPay;
    }

    public void setVocationWithPay(int vocationWithPay) {
        this.vocationWithPay = vocationWithPay;
    }
}
复制代码

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.username">root</property>
    <property name="connection.password">86915310</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/user</property>

    <!-- 配置hibernate的基本信息 -->
    <!-- hibernate所使用的数据库方言 -->
    <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    
    <!-- 是否在控制台打印SQL -->
    <property name="show_sql">true</property>
    
    <!-- 是否对SQL进行格式化 -->
    <property name="format_sql">true</property>
    
    <!-- 指定自动生成数据表的策略 -->
    <property name="hbm2ddl.auto">update</property>
    
    <!-- 设置hibernate的事务隔离级别 -->
    <property name="connection.isolation">2</property>
    
    <!-- 在执行完delete后可以把OID 设置为空 -->
    <!--  <property name="use_identifier_rollback">true</property>  -->
    
    <!-- 指定关联的.hbm.xml文件 -->
    <mapping resource="hibernate/sessiondemo/News.hbm.xml"/>
    <mapping resource="hibernate/sessiondemo/Worker.hbm.xml"/> 
    </session-factory>
</hibernate-configuration>
复制代码

Worker.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 Feb 20, 2016 4:22:33 PM by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="hibernate.sessiondemo">
    <class name="Worker" table="WORKER">
        <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>
        
        <!-- 映射组成关系 -->
        <component name="pay">
            <!-- 指定组成关系的组件的属性 -->
            <property name="monthlyPay" column="MONTHLY_PAY"></property>
            <property name="yearPay" column="YEAR_PAY"></property>
            <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property>
        </component>
    </class>
</hibernate-mapping>
复制代码

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 Feb 15, 2016 9:19:20 AM by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="hibernate.sessiondemo.News" table="NEWS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="title" type="string" column="TITLE" unique="true" update="false" index="news_index" length="20">
        </property>
        <property name="author" type="java.lang.String" index="news_index">
            <column name="AUTHOR" />
        </property>
        <property name="date" type="timestamp">
            <column name="DATE" />
        </property>
        
        <!-- 映射派生属性 -->
        <property name="desc" formula="(SELECT concat(AUTHOR, ':', TITLE) FROM NEWS n WHERE n.ID=ID)"> 
        </property>
    </class>
</hibernate-mapping>
复制代码

测试类:HibernateTest

复制代码
package hibernate.sessiondemo;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


public class HibernateTest {
    
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;
 
    @Before
    public void init(){
        // 1. 创建一个 SessionFactory 对象
        StandardServiceRegistry standardServiceRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();

        Metadata metadata = new MetadataSources(standardServiceRegistry).addAnnotatedClass(News.class)
                .addAnnotatedClassName("hibernate.sessiondemo.News").addResource("/hibernate/sessiondemo/News.hbm.xml")
                .getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE)
                .build();

        sessionFactory = metadata.getSessionFactoryBuilder().build();

        // 2. 创建一个 Session对象
        session = sessionFactory.openSession();
        System.out.println(session);

        // 3. 开启事务
        transaction = session.beginTransaction();
    }
    
    @After
    public void destroy(){
        // 5. 提交事务
        transaction.commit();

        // 6. 关闭session
        session.close();

        // 7. 关闭sessionFactory对象
        sessionFactory.close();
    }
    
    
    @Test
    public void testPropertyComponent(){
        Worker worker = new Worker();
        Pay pay = new Pay();
        pay.setMonthlyPay(1000);
        pay.setYearPay(80000);
        pay.setVocationWithPay(10);
        
        worker.setName("Javky");
        worker.setPay(pay);
        session.save(worker);
    }
    
    /**
     * 通过 SQL的语句来给类中的属性赋值
     * 1. 首先要生成属性的setter 和 getter方法
     * 2. 其次配置SQL 的 formula 属性:
     *  <!-- 映射派生属性 -->
     *  <property name="desc" formula="(SELECT concat(author, ':', title) FROM NEWS n WHERE n.id=id)"> 
     *  </property> 
     *  
     * 注意:
     *  1. formula="(sql)" 的英文括号不能少
     *  2. sql表达式中的列名和表名都应该和数据库对应,而不是和持久化对象的属性对应
     *  3. 如果需要在formula属性中使用参数,则直接使用WHERE cur.id=id 的形式, 其中id就是 和当前持久化对象的id属性对应的列 的id值将作为参数传入。                
     */
    
    @Test
    public void testPropertyFormula(){
        News news = session.get(News.class, 2);        
        System.out.println(news.getDesc());
    }
    
    
    /**
     *  在这个测是函数当中,因为title的属性被设置成了 update="false"
     *  所以这个测试函数中,
     *  news.setAuthor("Jack"); 会执行成功
     *  news.setTitle("yy"); 则执行失败
     *  但是hibernate不会报错也不会输出任何异常
     *  <property name="title" type="string" column="TITLE" unique="true" update="false" index="news_index" length="20">
     *  </property>
     */
    @Test
    public void testPropertyUpdate(){
        News news = session.get(News.class, 1);
        news.setAuthor("Jack");
        news.setTitle("yy");
    }
    
    @Test
    public void testHiloGenerator(){
        News news = new News("Yibu5", "RuiDian", new Date());
        session.save(news);
    }
        
    /**
     * <generator class="identity" />
     * 这种配置是自增的,要求底层数据库支持这种自增的方式。
     * 这种方式是线程安全的
     */
    @Test
    public void testIdentityGenerator() throws Exception{
        News news = new News("Yibu4", "RuiDian", new Date());
        session.save(news);
        
        Thread.sleep(5000);
    }
    /**
     *   <generator class="increment" />
     *   这种配置在每次插入之前都会先查找最大的index, 然后根据最大的index + 1
     *   但是他是线程不安全的,下面的例子中如果连续运行两次函数,第一次运行线程等待5s
     *   当第二次插入产生时,依然获取的是上一次的max + 1 这样OID就重复了,
     *   第二次插入失败: Duplicate entry '36' for key 'PRIMARY'
     *   
     *   开发的时候几乎不用这种生成方法,测试的时候可以使用
     */
    @Test
    public void testIncrementGenerator() throws Exception{
        News news = new News("Yibu3", "RuiDian", new Date());
        session.save(news);
        
        Thread.sleep(5000);
    }
    @Test
    public void testSave(){
        News news = new News();
        news.setAuthor("Cristianodadasdf");
        news.setTitle("EropCup2");
        news.setId(100);
        news.setDate(new Date());
        
        System.out.println(news);
        session.save(news);
        System.out.println(news);
    }
}
复制代码

需要引入的库文件:

猜你喜欢

转载自blog.csdn.net/pengzhisen123/article/details/80437568