本章代码 https://github.com/MarsOu1998/WebGenerator

1.Hibernate处理联合主键

如果在表中有两个列联合起来当主键,处理步骤如下
  1. 编写一个类(实现序列化接口),封装主键,并编写程序
  2. PO内编写各个属性,包括主键类型
  3. 在映射文件内写明:
<composite-id name="属性名" class="主键类名">
	<key-property name="属性名" column="列名"/>
	<key-property name="属性名" column="列名"/>
<composite-id/>

假设数据库内有一个UnionKey这个模型,里面有一张表叫做Student,Student表内是利用name和age作为联合主键的,查询步骤如下:

编写PO.StudentPK.java:

package PO;

import java.io.Serializable;

public class StudentPK implements Serializable {
    private String name;
    private int age;


    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

把联合主键的属性单独写一个类,然后在Student.java里面把StudentPK作为一个属性写成JavaBean风格。

Student.java:

package PO;

public class Student {
    private String sex;
    private StudentPK spk;

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public StudentPK getSpk() {
        return spk;
    }

    public void setSpk(StudentPK spk) {
        this.spk = spk;
    }
}

编写映射文件Student.hbm.xml:

package PO;

public class Student {
    private String sex;
    private StudentPK spk;

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public StudentPK getSpk() {
        return spk;
    }

    public void setSpk(StudentPK spk) {
        this.spk = spk;
    }
}

编写测试类test1.java:

package Test;

import PO.Student;
import PO.StudentPK;
import org.hibernate.Session;

public class test1 {
    public static void main(String[] args) {
        Session session=util.HibernateSessionFactory.getSession();
        StudentPK studentPK=new StudentPK();
        studentPK.setName("小明");
        studentPK.setAge(17);
        Student student= (Student)session.get(Student.class,studentPK);
        System.out.println(student.getSex());

        util.HibernateSessionFactory.closeSession();

    }
}

这样就可以获取17岁的小明的性别了。

主键生成策略generator

generator:主键生成器,英文是发电机的意思。每个主键都必须定义相应的主键生成策略。它用来为持久化类实例生成唯一的标识。

Hibernate内置的主键生成策略:

  1. assigned:由用户手工给一个值(例如账号由用户决定)
  2. increment:不用手工给值,由系统自动递增(这些只是Hibernate的策略)(比如在注册的时候,账号由系统给定的))

首先在配置文件里面的generator需要从assigned改成increment,当然,前提是数据库里面的账号,类型应该是int,不然会报错:

User.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">
<hibernate-mapping>
    <class name="PO.User" table="user2">
        <id name="account" column="account">
            <generator class="increment"></generator>
        </id>
        <property name="password" column="password"></property>
        <property name="name" column="name"></property>
    </class>
</hibernate-mapping>

Insert1.java:

package Test;

import PO.User;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class Insert1 {
    public static void main(String[] args) {
        Session session=util.HibernateSessionFactory.getSession();
        User user=new User();
        user.setPassword("oushile");
        user.setName("张三之王");
        Transaction transaction=session.beginTransaction();
        session.save(user);
        transaction.commit();
        util.HibernateSessionFactory.closeSession();
    }
}

系统会自动去查询当前数据库内最大的账号,然后在最大的基础上加一,就是自动递增的账号了。

  1. identity:由数据库生成主键
  2. sequence:由数据库根据序列生成主键
  3. hilo:根据Hibernate特殊算法生成主键
  4. native:系统自动选择identity,sequence,hilo
  5. uuid.hex:hibernate利用uuid算法生成主键
按照increment来生成主键
  1. 在数据库内定义一个整型主键
  2. 定义一个整型属性指向这个主键
  3. 为主键设置生成策略为increment
  4. 添加时,无需指定主键

2.动态模型

使用动态实体模型,可以不定义JavaBean:

  1. 在class标签中设置一个属性,entity-name=“实体名称” 并指明对应的表名
  2. 在每个property标签中,给定义一个type属性,指定该列对应的类型名称

每次利用Hibernate对数据库进行一定的操作时,JavaBean都是必不可少的,但是又很形式化,所以可以利用动态模型去省掉JavaBean的操作。

配置映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class entity-name="User"  table="user2">
        <id name="account" column="account" type="java.lang.Integer">
            <generator class="increment"></generator>
        </id>
        <property name="password" column="password" type="java.lang.String"></property>
        <property name="name" column="name" type="java.lang.String"></property>
    </class>
</hibernate-mapping>

这里把class从类名改为随便一个名字,name变为了entity-name,因为是动态的模型,系统不认识每个变量的类型了,java是强类型类型语言,所以需要在每一个属性后面,声明类型。

Insert2.java:

package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;

import java.util.HashMap;

public class Insert2 {
    public static void main(String[] args) {
        Session session=util.HibernateSessionFactory.getSession();
        //动态模型用HashMap容纳一个记录
        HashMap hashMap=new HashMap();
        hashMap.put("account",3);
        hashMap.put("password","oushile");
        hashMap.put("name","张三的儿子");

        Transaction transaction=session.beginTransaction();
        session.save("User",hashMap);
        transaction.commit();

        util.HibernateSessionFactory.closeSession();
    }
}

没了JavaBean,使用动态模型的时候就使用HashMap进行对象的存储。在save的时候指定动态模型的名字和HashMap的对象名即可。

利用对象存在方式:HashMap进行访问

get、load、save、saveOrUpdate、update