什么是ORM?
全称是:Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象
- O(Object 对象):JavaBean
- R(Relative 关系):关系型数据库
- M(Mapping 映射): 对象的映射,通过XML映射JavaBean
用到的jar包:
- Mysql-connector-java-8.0.18 连接MySql数据库8.0.18版本
Hibernate:
- Antlr-2.7.7.jar
- Classmate-1.3.0.jar
- Dom4j-1.6.1.jar
- Hibernate-commons-annotations-5.0.1.Final.jar
- Hibernate-core-5.2.10.Final.jar
- Hibernate-jpa-2.1-api-1.0.0.Final.jar
- Jandex-2.0.3.Final.jar
- Javassist-3.20.0-GA.jar
- Jboss-logging-3.3.0.Final.jar
- Jboss-transaction-api_1.2_spec-1.0.1.Final.jar
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.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456789</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="com/hibernate/entity/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
创建持久化类(javabean):
要求:
- private 私有类型;
- public 类型的setter和getter方法
- public 或 protected类型的无参数的构造方法
创建持久化类的配置文件
xxx.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 package="com.hibernate.entity">
<!-- name 类名 , table 表名(默认以类名作表名) ,<class>元素包含一个id 子元素以及多个property子元素-->
<class name="Customer" table="CUSTOMER">
<!--id和property的位置不能颠倒!!!!-->
<!-- id子元素设定持久化类的OID和表的主键的映射关系-->
<!-- column 指定表字段的名称 -->
<!-- generator 元素指定OID的生成器 -->
<id name="id" type="int" >
<column name = "ID"/>
<generator class="native" />
</id>
<!-- property子元素设定类的其他属性和表的字段的映射关系-->
<!-- name 对应类的属性名称-->
<!-- type 指定属性的类型-->
<!-- column 指定表字段的名称-->
<!-- not-null 指定属性是否允许为空-->
<property name="name" not-null="true" type="java.lang.String">
<column name="NAME"/>
</property>
...
</class>
</hibernate-mapping>
关系型数据库中区分不同记录
数据库中用主键来标识唯一性记录。
主键必须满足的条件:
- 不允许null
- 每条记录必须有唯一的主键值,主键值不能重复;
- 每条记录的主键值不能改变
主键分类:
- 业务(自然)主键:具有实际意义
- 代理主键:没有实际意义
Java程序中区分不同对象
Java语言中通过内存地址区分不同对象
两种比较引用变量方法
- “==” 比较两个变量引用的内存地址是否相同
- equals 比较两个变量引用的对象的值是否相同
用户自定义的类也可以覆盖Object的equals方法实现对象按值进行比较
Hibernate采用对象标识符OID区分对象
OID是关系型数据库表中的主键(通常是代理主键)在Java对象模型中的等价物
Hibernate采用OID来维持Java持久化类和数据库表中对应关系
Object Identifier
例子:
User u1 = (User) session.get(User.class,new Integer(1));
User u2 = (User) session.get(User.class,new Integer(1));
User u3 = (User) session.get(User.class,new Integer(2));
System.out.println(u1 == u2); //true
System.out.println(u1 == u3); //false
Hibernate允许在持久化类中把OID定义为一下三种类型:
为了保证OID的唯一性,通常由Hibernate或底层数据库给OID赋值
在关系映射配置文件中class元素的id子元素中用generator子元素指定OID生成器
<class name="User" table="USER">
<id name="id" type="int">
<generator class="identity"/>
</id>
</class>
generator的class属性有以下值:
- increment 采用hibernate数值递增的方式 --适合所有数据库,不依赖数据库系统,但只适合单个hibernate应用,不适合在集群情况下使用
- identity 采用数据库提供的自增长方式 --依赖数据库系统,需要数据库支持,mysql是支持的
- assigned 主键由应用逻辑产生 --由外部程序负责生成OID,与hibernate和数据库都无关
- 其他
一对多关系映射
联系(Relationship)
- 一对一联系 (1:1)
- 一对多联系(1:n)
- 多对多联系(m:n)
什么是一对多? (1:n)
举例:一张表中的 一条记录 对应 另一张表中 的 多条记录 ;反之不成立
一对多建表原则:在"多"的一方 创建外键 指向 “一” 的一方 的 主键,也就是many to one
比如:分类和商品联系,一个分类里面有多个商品,一个商品只能属于一个分类
比如:一个班级有很多个学生,每个学生只能在一个班级中学习
购物网站,用户可以有很多个订单,用户需要知道自己有哪些订单,商家需要通过某个订单属于哪个用户
单个用户就是(一),可以拥有很多个订单(多)
商家需要通过从很多订单中的某个订单(多)知道这个订单属于哪个用户(一)
—对于这种情况:
- 用户和订单之间的联系就是一对多
- 商家通过某个订单找出这个订单属于哪个用户就是多对一
- 商家和用户之间的联系就是多对多 (?)
第一个 一个用户拥有多个订单 ,所以是单向一对多
第二个 通过订单(或者多个订单)找到对应的某个用户,所以是单向多对一(从多个订单找一个)
第三个 不懂
Hibernate单向一对多关联
public class User{
private Integer id;
private String userName;
private String password;
private Set orderSet = new HashSet<Order>();
}
public class Order{
private Integer id;
private Double price;
}
<!-- name属性:指定要映射的属性名-->
<!-- cascade级联操作属性:save-update,delete,all,none-->
<set name = "orderSet" cascade="delete">
<!-- set的子元素-->
<!-- column属性设定所关联类对应表的外键-->
<!-- class属性设定所关联的类-->
<key column="USERID"/>
<one-to-many class="Order"/>
</set>
Hibernate双向一对多关联
- 当类与类建立了关联,很方便的从一个对象导航到一个或一组与之关联的对象。
- 如有了User对象,就可以通过User对象得到这个用户所有的订单信息,Set orders = user.getOrderSet()。
- 对于Order对象,如果想要得到这个订单属于哪个用户,怎么办呢?
也就是在Order类中增加user类型的属性
public class Order{
private Integer id;
private Double price;
private User user; //新增User类型的属性user
}
然后配置Order.hbm.xml
<many-to-one name="user" column="USERID" class="USER"/>
多对多关联映射
也就是一张表中的一条记录对应领一张表中的多条记录,反之也成立
一个学生可以选多个选修课,一个选修课也可以被多个学生选,这就是多对多
要实现选课这个例子:
首先是建表原则,要创建一个中间表,至少有两个字段,分别作为外键指向多对多双方的主键
实体多对多关联关系
数据库多对多关联
Hibernate多对多关联映射
public class Student{
private int id;
private String name;
private String sutdentNo;
private Set<Course> courseSet = new HashSet<Course>();
}
public class Course{
private Integer id;
private String name;
private int credit; //学分
private Set<Student> studentSet = new HashSet<Student>();
}
inverse是hibernate中双向关联关系中的基本概念,用来设置关系由哪一方维护
inverse=true 表示被控, =false表示主控
被控也就是放弃维护,由对方来维护
<set name="courseSet" table="STUDENTCOURSE" inverse="fasle">
<key column="STUDENTID"/>
<many-to-many class="Course" column="COURSEID"/>
</set>
<set name="studentSet" table="STUDENTCOURSE" inverse="true">
<key column="COURSEID"/>
<many-to-many class="Student" column="STUDENTID"/>
</set>
一对一关系映射
举例:网贷系统要求实名认证,也就是一人一证,一个账号只能绑一个身份证,一个人也只能注册一个号
要求在User.hbm.xml中设定级联属性
<one-to-one name="person" class="Person" cascade="all"/>
在Person.hbm.xml设定
<id name="id">
<!-- 设定外键-->
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<!-- constrained属性为true,表明person表id为外键,参照主表user-->
<one-to-one name="user" constrained="true"/>
通过外键关联映射-外键表(User)
<!-- column指明外键列
unique为true 表明唯一约束
cascade属性设置为all 表名删除User时同时删除PERSON
-->
<many-to-one name="person" column-"PERSON" cascade="all" unique="true"/>
唯一外键关联映射 主键表PERSON
<!-- property-ref属性,表名建立了从User到Person的一对一关联关系-->
<one-to-one name="user" property-ref="person"/>