AQ#說明
1.基礎(chǔ)的jar包
required + jpa + mysql數(shù)據(jù)庫連接
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 關(guān)系
數(shù)據(jù)庫表
M Mapping 映射
dao中的增刪改查操作 方式:1.xx.hbm.xml 2.注解
ORM是規(guī)則是概念
ORM的實現(xiàn)
hibernate框架
mybatis框架
自己代碼實現(xiàn)(反射)
3.對dao操作,有哪些選擇襟交,優(yōu)缺點
1.jdbc
2.DbUtils組件
3.自己封裝jdbc工具類邓线,簡化jdbc操作
4.hibernate框架
5.mybatis框架
對比
執(zhí)行效率最高:純jdbc操作
開發(fā)效率最高:hibernate
兼容性好:hibernate桑腮,可以跨數(shù)據(jù)庫平臺
4.使用步驟:
1.建庫生宛、建表
2.寫實體類
3.寫映射文件
4.寫數(shù)據(jù)庫配置文件
5.測試api
基本映射 base
主鍵映射
基本主鍵映射
復合主鍵映射
復合屬性 compattr
修改列名2種方式
集合映射 collection
基本數(shù)據(jù)類型/自定義類型
List
Set
Map
關(guān)聯(lián)映射 oneway/bothway
單向關(guān)聯(lián)(一邊配置關(guān)聯(lián)):oneway
一對一(1--1):
一對多(1--N):
多對一(N--1):
多對多(N--N):
雙向關(guān)聯(lián)(兩邊配置關(guān)聯(liá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();
//數(shù)據(jù)庫操作
transaction.commit();
基礎(chǔ)
//1.注解方式
@Entity //把pojo轉(zhuǎn)化成持久化類
@Table(name="user") // 指定表名
public class User {
@Id //主鍵列
@GeneratedValue(strategy=GenerationType.AUTO) //自增長
@Column(name="u_id") //指定數(shù)據(jù)庫列名 如果不寫就跟屬性名一致 (映射列名 )
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") //規(guī)定長度 和 初始化值
private int age;
@Column(name="u_address",
insertable=false, // 不允許插入
updatable=false)// 不允許修改
private String address;
@Column(name="u_salary", precision=6, // 總位數(shù)
scale=2) // 小數(shù)點后面位數(shù)
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 自增長但是不支持并發(fā)
assigned 手動指定主鍵的值
uuid 使用uuid做為主鍵 主鍵是String類型
foreign 外鍵策略 一對一映射時用到
-->
主鍵/聯(lián)合主鍵
//主鍵
@Entity
@Table(name="user")
public class User {
/*
* GenerationType.IDENTITY: 適宜MySQL、SqlServer有自增長列的數(shù)據(jù)庫
* GenerationType.SEQUENCE:適宜Oracle這種沒有自增長有sequence的數(shù)據(jù)庫
* GenerationType.AUTO:讓Hibernate根據(jù)數(shù)據(jù)庫方言自動選擇主鍵生成策略
* GenerationType.TABLE: 適宜所有的數(shù)據(jù)庫,因為它會單獨生成一張表來維護主鍵生成
* */
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
}
//聯(lián)合主鍵
public class PersonKey implements Serializable{
private String firstName;
private String lastName;
}
@Entity
@Table(name="Person")
public class Person {
@Embedded
private PersonKey key;
}
//修改聯(lián)合主鍵表中名字-第一種方式
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;
}
//修改聯(lián)合主鍵表中名字-第二種方式
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{}
注意:
所有的持久化都會生成表(子類會把父類中的屬性繼承過來生成在自己的表中)
這種策略主鍵不能用自增長
查詢時會出現(xiàn)union運算
總結(jié)保存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
總結(jié)
雙向關(guān)聯(lián)
多對多
多對一
一對多
一對一
單向關(guān)聯(lián)
多對多
多對一
一對多
一對一
雙向關(guān)聯(lián)
先保存主表法精,再保存從表
有mappedBy的類中是主表多律。
單向關(guān)聯(lián)
先保存主表痴突,再保存從表
有@JoinColumn的類是從表。
單向關(guān)聯(lián)-一對一
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表中創(chuàng)建一個s_id的字段狼荞,用來存儲一條student數(shù)據(jù)的sid
referencedColumnName:關(guān)聯(lián)student表中的sid字段
單向關(guān)聯(lián)-一對多
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字段辽装,關(guān)聯(lián)的是teacher表中的tid字段。
單向關(guān)聯(lián)-多對一
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表中創(chuàng)建一個t_id字段相味,關(guān)聯(lián)teacher表中的tid字段
單向關(guān)聯(lián)-多對多
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 :
雙向關(guān)聯(lián)-一對一
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表中創(chuàng)建一個t_id的字段拾积,關(guān)聯(lián)teacher表中的tid字段
@OneToOne(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")
mappedBy :表示teacher表不維護關(guān)聯(lián)字段。交給student表管理丰涉。
雙向關(guān)聯(lián)-一對多
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表中創(chuàng)建一個t_id字段拓巧,關(guān)聯(lián)teacher表中的tid字段
@OneToMany(fetch=Fetch.LAZY,targetEntity=Student.class,mappedBy="teacher")
mappedBy :表示不維護關(guān)聯(lián)字段
雙向關(guān)聯(lián)-多對多
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 :