Hibernate-note04

1.Hibernate Annotation
Annotation这个文件是替代掉的是pojo中的映射文件,
它不能替换hibernate.cfg.xml,不能替换掉hibernate的配置文件,但是这个配置文件在
spring中会被替换掉


01.在hibernate.cfg.xml配置,
首先要去掉再配置文件中的映射文件的配置,去掉下面这段
<!-- 映射文件的配置,这里resource指的是磁盘的目录,所以是"/"不是"." -->
<mapping resource="com/kaishengit/pojo/User.hbm.xml" />
<mapping resource="com/kaishengit/pojo/Address.hbm.xml" />
<mapping resource="com/kaishengit/pojo/person.hbm.xml" />
<mapping resource="com/kaishengit/pojo/card.hbm.xml" />
<mapping resource="com/kaishengit/pojo/student.hbm.xml" />
<mapping resource="com/kaishengit/pojo/teacher.hbm.xml" />


02.然后再相同的位置加上,注意不同,


   以前是resource现在是class
<!-- 实体类的配置,对应映射的是哪个实体类" -->
<mapping class="com.kaishengit.pojo.User"/>


03.在pojo实体类中的配置
拿User类来举例子
<hibernate-mapping package="com.kaishengit.pojo">
<class name="User" table="t_user">
<cache usage="read-write" />
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<property name="age"></property>
<set name="addressSet" inverse="true" cascade="delete" fetch="join" order-by="id desc">
<key column="user_id"></key>
<one-to-many class="Address" />
</set>
</class>
</hibernate-mapping>


----------------------当实体类和表是相对应的关系的时候------------------------
-------------------------即没有addressSet的时候-------------------------------


package com.kaishengit.pojo;


import java.io.Serializable;
import java.util.Set;


import javax.annotation.Generated;
//以包javax.persistence开头的都是jpa的规范了,
//jpa里面规定的都是注解
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;


import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
//这就体现了在hibernate中会是annotation和jpa掺着用


@Entity                    //表示这是一个实体类
@Table(name="t_user")        //映射的表,告诉它对应的表示哪一个
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
                          //缓存是可读可写
public class User implements Serializable {

private static final long serialVersionUID = 1L;

private int id;
private String name;
private int age;
//private Set<Address> addressSet;//没有这项

// //get/set
//开始配置属性了
//表的各列的映射都是在对应的getXX方法上面的
//即属性的配置都要加载getXX上面
@Id    //因为id是个特殊的属性,所以直接id就可以了
@GeneratedValue(strategy=GenerationType.IDENTITY)
//主键自动增长
public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}
@Column(name="name")//假如不一样的时候可以这样配置
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;
}
// public Set<Address> getAddressSet() {
// return addressSet;
// }
//
// public void setAddressSet(Set<Address> addressSet) {
// this.addressSet = addressSet;
// }


}


测试:
session.beginTransaction();
User user=new User();
user.setAge(36);
user.setName("anno");
session.save(user);
session.getTransaction();


2.一对多和多对一,这个要配置外键


 01.配置一这端的表的实体类User的annotation
还是User为例子,我们把addressSet释放进来,根据配置可以看到User是一对多
我们知道在一对多和多对一的时候我们把关系维护交给多的那个来维护(校长)
所以User不用配置关系维护


@Entity                    //表示这是一个实体类
@Table(name="t_user")        //映射的表,告诉它对应的表示哪一个
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
                          //缓存是可读可写
public class User implements Serializable {

private static final long serialVersionUID = 1L;

private int id;
private String name;
private int age;
private Set<Address> addressSet;//没有这项

// //get/set
//开始配置属性了
//表的各列的映射都是在对应的getXX方法上面的
//即属性的配置都要加载getXX上面
@Id    //因为id是个特殊的属性,所以直接id就可以了
@GeneratedValue(strategy=GenerationType.IDENTITY)
//主键自动增长
public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}
@Column(name="name")//假如不一样的时候可以这样配置
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;
}
   public List<Address> getAddressSet() {
return addressSet;
}


@OneToMany(mappedBy="user")
//这里写的有个mappedBy,只要写这个就表示放弃维护关系
//它的值是你当前的类在多的那个实体类中存的属性的名字
//不是外键的名字
public void setAddressSet(List<Address> addressSet) {
this.addressSet = addressSet;
}

}


 02.并且要把里面的set集合变成list集合


 03.配置多这端的表的实体类Address的annotation
@Entity
@Table(name="t_address")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Address {
private int id;
private String tel;
private String address;
private User user;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@ManyToOne(cascade=CascadeType.REMOVE)
@JoinColumn(name="user_id")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}


NOTE:
@ManyToOne(cascade=CascadeType.REMOVE)//javax.persistence.CascadeType包,
//这个不是必须的需要的时候要写
@ManyToOne(cascade=CascadeType.REMOVE,fetch=FetchType.EAGER)


@ManyToOne中有四个属性01.cascade=CascadeType.REMOVE----级联删除
02.fetch=FetchType.EAGER----抓取策略,这个有2个值是Lazy和EAGEN,注意区别
@JoinColumn(name="user_id")//配置外键


04.记得在hibernate中加上实体类配置
<mapping class="com.kaishengit.pojo.Address"/>




这时候可能会出现一个异常,这个异常在一对一和一对多时候会出现,多对多不会出现
java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z异常


exception


使用spring + hibernate annotations的@OneToMany 一对多双向关联后出现异常: 
java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z 
出现这种异常通常是由于Myeclipse的javaee.jar 版本较低,与Hibernate等自带的JPA出现了冲突。 
网上一些处理方法是删除项目里的 删除 建立web项目时自带的Javaee.jar,可是这样带来的后果是 httpServletRequest 等组件无法使用。 
对于tomcat我目前的解决方法是: 
1. 在 D:\Program Files\Genuitec\Common\plugins下搜索 EE_5 找到EE_5 文件夹; 
2. 进去EE_5文件夹 右键 javaee.jar 打开方式 WINRAR压缩文件管理器,进去里面删除persistence文件夹 这个子文件夹。


对于weblogic我的解决方法是: 
把hibernate-jpa-2.0-api-1.0.0.Final.jar放到D:\Program Files\weblogic\jdk160_05\jre\lib\ext 就没问题了。 
(如果不行,可以考虑先尝试tomcat的解决方案,再接着试weblogic的。tomcat是修改java的jdk文件,而weblogic是修改本服务器里面的文件)


总结:这样解决后,当写一对一的时候,就会无法识别 
@OneToOne 
@PrimaryKeyJoinColumn 
最好还是用jEE6来建,这样就不会有包不兼容的问题


3.多对多,这个要配置关联表


多对多的时候,可以选择任意一方来维护关系,另外一方不用管
这时候,不维护关系的一方配置和一对多的时候,一那一端的配置一样
  01.Teacher方配置
注意关系映射在类中的属性即可


@ManyToMany(mappedBy="studentSet")
public List<Teacher> getTeacherSet() {
return teacherSet;
}


  02.Student,维护关系方的配置


    @ManyToMany()
@JoinTable(name="t_teacher_student",joinColumns={@JoinColumn(name="tea_id")},
         inverseJoinColumns={@JoinColumn(name="stu_id")})
public List<Student> getStudentSet() {
return studentSet;
}


  Note:
      @ManyToMany()
 @JoinTable(name="t_teacher_student",joinColumns={@JoinColumn(name="tea_id")},
         inverseJoinColumns={@JoinColumn(name="stu_id")})
      @JoinTable是配置关系表,就是中间表


 属性要有表名---name="t_teacher_student",
    映射外键---这里面放的都是数组,用{}表示
    ---joinColumns={@JoinColumn(name="tea_id")},//这里放的是本身这个类在关系表
    中的列名
    ---inverseJoinColumns={@JoinColumn(name="stu_id")}
    //这里放的是另一个表对应的类在关系表中映射的列名


  测试:Teacher t=(Teacher)session.get(Teacher.class, 19);
System.out.println(t.getName());
List<Student> list=t.getStudentSet();
for(Student s:list){
System.out.println(s.getName());
}


4.一对一
  这种是card表的id既当主键也当外键的情况


   01.person类


@OneToOne
@PrimaryKeyJoinColumn //意思就是card会引用到我们当前这张表的主键,
//就是说我们这个表主键会是card表的外键
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}


   02.Card类
@Id
@GenericGenerator(name="fk",strategy="foreign",
parameters={@Parameter(name="property",value="person")})


@GeneratedValue(generator="fk")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}

@OneToOne(mappedBy="card")//告诉对方,让他自己管理自己的主键
@PrimaryKeyJoinColumn
public Person getPerson() {
return person;
}
---------------------------------------------------------------
<hibernate-mapping package="com.kaishengit.pojo">


<class name="Card" table="t_card">
<id name="id" column="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="cardNum" column="cardnum"></property>
<one-to-one name="person" class="Person"></one-to-one>
</class>


</hibernate-mapping>




note:
@Id //这时id的生成策略就变了不再是自动增长
//首先写一个生成器
@GenericGenerator(name="fk",strategy="foreign",
parameters={@Parameter(name="property",value="person")})
//然后给生成器取个名字,name="fk",
//生成策略strategy="foreign",//是外键
parameters={@Parameter(name="property",value="person")}
//对应<param name="property">person</param>//属性是property,值是person


@GeneratedValue(generator="fk")//告诉它生成器的名字




测试:  Person p = (Person) session.get(Person.class, 4);
System.out.println(p.getName());
System.out.println(p.getCard().getCardNum());


5.主键UUID,不用自动增长型
因为有的公司不用自动增长型,
例如01电信,每条短信都会存在数据库里,数据量太大,很会超出long long。
02.公司出现导表,a职员的表数据都到20了,b职员导进来的表才到10,就会冲突


 01.建一个id和name的t_uuid表


 02.创建它的实体类
@Entity
@Table(name="t_uuid")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class IdUUID {
private String id;
private String name;

@Id
/*@GeneratedValue(strategy=GenerationType.AUTO   //自动//
GenerationType.IDENTITY //自动增长
GenerationType.SEQUENCE //序列
GenerationType.TABLE)*/ //table
@GenericGenerator(name="myuuid",strategy="uuid")  //由于默认的增长策略没有uuid
//所以自己写个生成器,生成器名字name="myuuid",
//,strategy="uuid"这个是hibernate提供的uuid策略,它提供有十几种,包括用过的
//  foreign和native等


public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}


}
添加:<mapping class="com.kaishengit.pojo.IdUUID"/>//spring不用添加

测试:
IdUUID temp = new IdUUID();
temp.setName("aaaa");
session.save(temp);
session.getTransaction().commit();
id:8a9c9aba4ee42bb4014ee42bb5c90000//这个和我们平时生成的不太一样,
它中间没有横线-,是一个32为的uuid


6.排序
我们尽量用List不要用Set?考证


@ManyToMany(mappedBy="students")
@OrderBy("id desc")//多个的话用,隔开
public List<Teacher> getTeachers() {
return teachers;
}
7.排除不进行持久化操作的属性

如果写一个与数据库属性操作无关的方法,但是也是getXX这种格式。
并不和数据库对应,这时需要加上@Transient
不然会报错


@Transient
public int getOtherItems() {
return age;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值