AQ#说明
1.基础的jar包
required + jpa + mysql数据库连接
1.下载地址
http://hibernate.org/orm/downloads/
https://sourceforge.net/projects/hibernate/files/hibernate-orm/
https://sourceforge.net/projects/hibernate/files/
2.ORM概念
O Object 对象
Java对象
R Relation 关系
数据库表
M Mapping 映射
dao中的增删改查操作 方式:1.xx.hbm.xml 2.注解
ORM是规则是概念
ORM的实现
hibernate框架
mybatis框架
自己代码实现(反射)
3.对dao操作,有哪些选择,优缺点
1.jdbc
2.DbUtils组件
3.自己封装jdbc工具类,简化jdbc操作
4.hibernate框架
5.mybatis框架
对比
执行效率最高:纯jdbc操作
开发效率最高:hibernate
兼容性好:hibernate,可以跨数据库平台
4.使用步骤:
1.建库、建表
2.写实体类
3.写映射文件
4.写数据库配置文件
5.测试api
基本映射 base
主键映射
基本主键映射
复合主键映射
复合属性 compattr
修改列名2种方式
集合映射 collection
基本数据类型/自定义类型
List
Set
Map
关联映射 oneway/bothway
单向关联(一边配置关联):oneway
一对一(1--1):
一对多(1--N):
多对一(N--1):
多对多(N--N):
双向关联(两边配置关联):两边都可以查询 bothway
一对一(1--1):@OneToOne 加了mappedBy的表时主表,另外一张是从表
一对多(1--N):
多对多(N--1):@ManyToMany
从表中生成外键,配置@JoinCloumn的是从表 先保存主表,再保存从表
继承映射 extend
所有的持久化都会生成表(子类表会引用父类表的主键列)
单个表(只生成一张表)
所有的持久化都会生成表(子类会把父类中的属性继承过来生成在自己的表中)
代码
onfiguration cf = new Configuration();
cf.configure("com/shuai/hibernate/bothway/onetomany/hibernate.cfg.xml");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(cf.getProperties()).build();
SessionFactory sessionFactory = cf.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
//数据库操作
transaction.commit();
基础
//1.注解方式
@Entity //把pojo转化成持久化类
@Table(name="user") // 指定表名
public class User {
@Id //主键列
@GeneratedValue(strategy=GenerationType.AUTO) //自增长
@Column(name="u_id") //指定数据库列名 如果不写就跟属性名一致 (映射列名 )
private int id;
@Column(name="u_name", //列名
length=50, //长度
nullable=true, //非空约束
unique=true)// 唯一约束
private String name;
@Column(name="u_age", //列名
columnDefinition="int(10) NOT NULL default 20") //规定长度 和 初始化值
private int age;
@Column(name="u_address",
insertable=false, // 不允许插入
updatable=false)// 不允许修改
private String address;
@Column(name="u_salary", precision=6, // 总位数
scale=2) // 小数点后面位数
private BigDecimal salary;
@Lob // 映射大的二进制或大的文本
private byte[] pictrue;
/*
* TemporalType.DATE : yyyy-MM-dd
* TemporalType.TIME : HH:mm:ss
* TemporalType.TIMESTAMP : yyyy-MM-dd HH:mm:ss
* */
@Temporal(TemporalType.TIMESTAMP) //日期格式
private Date birthday;
@Transient // @Transient|transient 指定不是持久化的属性(不会生成表中列)
private String remark;
}
//2.配置文件方式
public class User {
private int id;
private String name;
private String password;
}
//配置User.hbm.xml
<class name="com.shuai.hibernate.domain.User" table="t_user">
<id name="id" column="u_id">
<generator class="native"></generator>
</id>
<property name="name" column="u_name"></property>
<property name="password" column="u_password"></property>
</class>
<!--
class 是映射一个对象
name 是Java类
table 是表
property 映射属性
name 是类的属性名
column 是表中的属性名
length 是指定表中字段的长度 默认是255
type 是表中字段的类型
not-null 是否能为空 非空约束
unique 是否唯一 唯一约束
id 是主键映射 在hibernate中表中必须要有主键
generator 主键生成策略
native 主键自增长
identity MySQL中的自增长方式
sequence Oracle中的序列增长方式
increment 自增长但是不支持并发
assigned 手动指定主键的值
uuid 使用uuid做为主键 主键是String类型
foreign 外键策略 一对一映射时用到
-->
主键/联合主键
//主键
@Entity
@Table(name="user")
public class User {
/*
* GenerationType.IDENTITY: 适宜MySQL、SqlServer有自增长列的数据库
* GenerationType.SEQUENCE:适宜Oracle这种没有自增长有sequence的数据库
* GenerationType.AUTO:让Hibernate根据数据库方言自动选择主键生成策略
* GenerationType.TABLE: 适宜所有的数据库,因为它会单独生成一张表来维护主键生成
* */
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
}
//联合主键
public class PersonKey implements Serializable{
private String firstName;
private String lastName;
}
@Entity
@Table(name="Person")
public class Person {
@Embedded
private PersonKey key;
}
//修改联合主键表中名字-第一种方式
public class PersonKey implements Serializable{
private String firstName;
private String lastName;
}
@Entity
@Table(name="Person")
public class Person {
@Embedded
@AttributeOverrides({@AttributeOverride(name="firstName", column=@Column(name="F_NAME")),
@AttributeOverride(name="lastName", column=@Column(name="L_NAME"))})
private PersonKey key;
}
//修改联合主键表中名字-第二种方式
public class PersonKey implements Serializable{
@Column(name="FIRST_NAME")
private String firstName;
@Column(name="LAST_NAME")
private String lastName;
}
@Entity
@Table(name="Person")
public class Person {
@Embedded
private PersonKey key;
}
//配置文件
public class PersonKeys implements Serializable{
private String username;
private int password;
}
public class Person {
private PersonKeys keys;
private int age;
}
//Person.hbm.xml配置
<class name="com.shuai.hibernate.domain.Person" table="t_person">
<composite-id name="keys">
<key-property name="username"></key-property>
<key-property name="password"></key-property>
</composite-id>
<property name="age" column="u_age"></property>
</class>
继承体系中生成表的情况 InheritanceType.JOINED
@Entity
@Table(name="person") //生成person表
@Inheritance(strategy=InheritanceType.JOINED) //所有的持久化都会生成表(子类表会引用父类表的主键列)
public class Person{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
}
@Entity
public class Student extends Person{
private String subject;
}
注意:
@Inheritance(strategy=InheritanceType.JOINED)
所有的持久化都会生成表(子类表会引用父类表的主键列)
继承体系中生成表的情况 InheritanceType.SINGLE_TABLE
@Entity
@Table(name="person") //生成person表
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)// 单个表
@DiscriminatorColumn(name="per_stu",discriminatorType=DiscriminatorType.INTEGER)// 辨别者列
@DiscriminatorValue("1")// 辨别者列值
public class Person {}
@Entity
@DiscriminatorValue("2") //辨别者列值
public class Student{}
注意:
@DiscriminatorColumn(name="per_stu",discriminatorType=DiscriminatorType.INTEGER)// 辨别者列
person表中会生成一个per_stu列。
当存入Person对象时,per_stu列的值是1
当存入Student对象时,per_stu列的值是2
继承体系中生成表的情况
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)// 所有的持久化都会生成表(子类会把父类中的属性继承过来生成在自己的表中)
public class Person{}
@Entity
public class Student{}
注意:
所有的持久化都会生成表(子类会把父类中的属性继承过来生成在自己的表中)
这种策略主键不能用自增长
查询时会出现union运算
总结保存List/Set/Map
List
@ElementCollection
@CollectionTable
@OrderColumn
@Embeddable - 注解集合中的类
Set
@ElementCollection
@CollectionTable
@Embeddable - 注解集合中的类
Map
@ElementCollection
@CollectionTable
@MapKeyColumn
@Embeddable - 注解集合中的类
保存List
Person.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)
@CollectionTable(name="address")
@OrderColumn(name="a_id")
private List<String> address = new ArrayList<String>();
注意:
@OrderColumn(name="a_id")
a_id是自增长id
@CollectionTable(name="address")
address是表名
生成的address表中会有一个Person_id 是Person的主键id
@Embeddable
Address.java
里面就是一些属性,可以没有主键
此类不会生成表
User.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=Address.class)
@CollectionTable(name="user_address")
@OrderColumn(name="u_a_id")
private List<Address> address = new ArrayList<Address>();
注意:
@OrderColumn(name="u_a_id")
u_a_id 是自增长的id
@CollectionTable(name="user_address")
user_address是表名
生成的user_address表中会有一个User_id是user表的主键id
保存Set
Person.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)
@CollectionTable(name="p_address")
private Set<String> address = new HashSet<String>();
注意:
@CollectionTable(name="p_address")
p_address 是表名
在表中会有一个Person_id是person表中的主键
@Embeddable
Address.java
里面就是一些属性,可以没有主键
此类不会生成表
User.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=Address.class)
@CollectionTable(name="user_address")
private Set<Address> address = new HashSet<Address>();
注意:
@CollectionTable(name="user_address")
user_address 是表名
在表中会有一个User_id是user表中的主键
保存Map
Person.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)
@CollectionTable(name="p_address")
@MapKeyColumn(name="m_key")
private Map<String,String> address = new HashMap<String,String>();
注意:
@MapKeyColumn(name="m_key")
是Map的键
@CollectionTable(name="p_address")
是表名
在生成的表中会有一个Person_id对应person表中的id
@Embeddable
Address.java
里面就是一些属性,可以没有主键
此类不会生成表
User.java
@ElementCollection(fetch=FetchType.LAZY,targetClass=Address.class)
@CollectionTable(name="user_address")
@MapKeyColumn(name="map_key")
private Map<String,Address> address = new HashMap<String,Address>();
注意:
@MapKeyColumn(name="map_key")
是Map的键
@CollectionTable(name="user_address")
是表名
在生成的表中会有一个User_id对应user表中的id
总结
双向关联
多对多
多对一
一对多
一对一
单向关联
多对多
多对一
一对多
一对一
双向关联
先保存主表,再保存从表
有mappedBy的类中是主表。
单向关联
先保存主表,再保存从表
有@JoinColumn的类是从表。
单向关联-一对一
Teacher.java
@OneToOne(fetch=FetchType.LAZY,targetEntity=Student.class)
@JoinColumn(name="s_id",unique=true,referencedColumnName="sid")
private Student student;
Student.java
private int sid;
注意:
@JoinColumn(name="s_id",unique=true,referencedColumnName="sid")
name:在teacher表中创建一个s_id的字段,用来存储一条student数据的sid
referencedColumnName:关联student表中的sid字段
单向关联-一对多
Teacher.java
private int tid;
@OneToMany(fetch=FetchType.LAZY,targetEntity=Student.class)
@JoinColumn(name="t_id",referencedColumnName="tid")
private Set<Student> students = new HashSet<Student>();
Student.java - 保存外键
private int sid;
注意:
@JoinColumn(name="t_id",referencedColumnName="tid")
name :会在student表中添加t_id字段,关联的是teacher表中的tid字段。
单向关联-多对一
Teacher.java
private int tid;
Student.java - 保存外键
@ManyToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)
@JoinColumn(name="t_id",referencedColumnName="tid")
private Teacher teacher;
注意:
@JoinColumn(name="t_id",referencedColumnName="tid")
name :会在student表中创建一个t_id字段,关联teacher表中的tid字段
单向关联-多对多
Teacher.java
private int tid;
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Student.class)
@JoinTable(name="t_tech_stu",
joinColumns=@JoinColumn(name="t_id",referencedColumnName="tid"),
inverseJoinColumns=@JoinColumn(name="s_id",referencedColumnName="sid"))
private Set<Student> students = new HashSet<Student>();
Student.java
private int sid;
注意:
@JoinTable(name="t_tech_stu",
joinColumns=@JoinColumn(name="t_id",referencedColumnName="tid"),
inverseJoinColumns=@JoinColumn(name="s_id",referencedColumnName="sid"))
name :是中间表名
joinColumns :
inverseJoinColumns :
双向关联-一对一
Teacher.java
private int tid;
@OneToOne(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")
private Student student;
Student.java
private int sid;
@OneToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)
@JoinColumn(name="t_id",referencedColumnName="tid",unique=true)
private Teacher teacher;
注意:
@JoinColumn(name="t_id",referencedColumnName="tid",unique=true)
name :在student表中创建一个t_id的字段,关联teacher表中的tid字段
@OneToOne(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")
mappedBy :表示teacher表不维护关联字段。交给student表管理。
双向关联-一对多
Teacher.java
private int tid;
@OneToMany(fetch=Fetch.LAZY,targetEntity=Student.class,mappedBy="teacher")
private Set<Student> students = new HashSet<Student>();
Student.java
private int sid;
@ManyToOne(fetch=Fetch.LAZY,targetEntity=Teacher.class)
@JoinColumn(name="t_id",referencedColumnName="tid")
private Teacher teacher;
注意:
@JoinColumn(name="t_id",referencedColumnName="tid")
name :在student表中创建一个t_id字段,关联teacher表中的tid字段
@OneToMany(fetch=Fetch.LAZY,targetEntity=Student.class,mappedBy="teacher")
mappedBy :表示不维护关联字段
双向关联-多对多
Teacher.java
private int tid;
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teachers")
private Set<Student> students = new HashSet<Student>();
Student.java
private int sid;
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Teacher.class)
@JoinTable(name="t_teach_stu",
joinColumns=@JoinColumn(name="s_id",referencedColumnName="sid"),
inverseJoinColumns=@JoinColumn(name="t_id",referencedColumnName="tid"))
private Set<Teacher> teachers = new HashSet<Teacher>();
注意:
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teachers")
mappedBy : 表示不维护外键
@JoinTable(name="t_teach_stu",
joinColumns=@JoinColumn(name="s_id",referencedColumnName="sid"),
inverseJoinColumns=@JoinColumn(name="t_id",referencedColumnName="tid"))
name :中间表名
joinColumns :
inverseJoinColumns :