hibernate

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 :
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容