CascadeType.PERSIST (级联新建)
CascadeType.REMOVE (级联删除)
CascadeType.REFRESH (级联刷新)
CascadeType.MERGE (级联更新)中选择一个或多个。
CascadeType.ALL
有时候CascadeType不行,
解决方法:利用hibernate的自定义的级联删除,不要使用jpa的
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
.....................//
@OneToMany(mappedBy="enterprise")
@Cascade(value={CascadeType.SAVE_UPDATE})
................................//
Class Level:
1:通过@Entity声明当前pojo为实体Bean
2:通过@Table定义对应数据库表的属性
name:表名,默认实体类名
uniqueConstraints:定义表的唯一性约束
@Entity
@Table( name = "tb_user",
uniqueConstraints ={@UniqueConstraint(columnNames = "userName")})
public class User implements Serializable {
private Integer id;
private String userName;
}
主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
或者
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
Method Level
@Basic
@Transient
@Column
所有非static非transient都会被持久化,也就是说所有加@Transient是不会被保存到数据库中的,所有没有加注的默认为@Basic,通过Column我们可以更一步的定义列名,是否为空,长度,是否可更新等等属性值,
这里设置的name,比如actcodeId,那么数据库中就是actcode_id
@Column(name = "actcodeId", updatable = false, nullable = true, length = 36)
@Column(name = "userName", nullable = false, length = 80, unique = true)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Transient
public String getPassword() {
return password;
}
默认的列名就是属性名,上面的name="userName"只是演示而已。
password加注为@Transient,所以通过SchemaExport导入Schema,查看表结构是没有这个字段的。
@Formula
@Formula(" (select COUNT(*) from school_info) ")
private int count;
@Temporal
日期类型,分三种,Time,Date,Timestamp
@Temporal(TemporalType.TIMESTAMP)
public Date getBirthday() {
return birthday;
}
@Lob
1:所有的Clob,Character,char,String都会被转为Clob
2:所有的Blob,Byte[],byte[],serializable都会被转为Blob
POJO中有一个private String content;的属性,按ejb3配成@Lob后,被处理成了text类型,text 64k的存储容量还是比较可怜了。
@Lob
@Column(columnDefinition = "LongText")
@Lob
public Clob getResume() {
return resume;
}
@Lob
public Blob getImage() {
return image;
}
级联策略
在ejb3-persistence.jar中只定义了ALL、MERGE、PERSIST、REFRESH、REMOVE,比较恶心的就是,删除对象的时候,并不会级联删除关联对象,而是用update xx set parent_id=null where parent_id=?这类语句把关系干掉了事。不得已,在这儿用了hibernate的DELETE_ORPHAN。
@OneToMany(targetEntity = Attachment.class)
@Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN,
org.hibernate.annotations.CascadeType.ALL})
@JoinColumn(name = "info_id")
CACHE
ejb3-persistence.jar里面没有找到cache的配置,继续请出hibernate来干活
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Table(name = "T_INFO")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
实例
@Entity
Public class Troop{
@OneToMany(mappedBy = "troop")
Public Set<Solder> getSolders(){}
}
@Entity
Public class Solder{
@ManyToOne
@JoinColumn(name="troop_fk")
Public Troop getTroop(){}
}
Troop通过troop属性和Solder建立了一对多关的双向关联,在mappedBy端不必也不能再定义任何物理映射。对以一对多的双向关联,如果要一对多这一端维护关联关系,需要删除mappedBy元素并将多对以这一段的@JoinColumn的inserttable和updatetable设置为false。
// mappedBy="school"就相当于inverse=true,(mappedBy指定的是不需要维护关系的一端)
// 应该注意的是mappedBy值对应@ManyToOne标注的属性,我刚开始写成"schoolId",让我郁闷了好一会
@OneToMany(mappedBy = "school", cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = UserMember.class)
// 用范性的话,就不用targetEntity了
private List<usermember> users = </usermember>new ArrayList<usermember>(); </usermember>
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "school_info")
public class SchoolInfo implements java.io.Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;//hibernate的uuid机制,生成32为字符串
@Column(name = "actcodeId", updatable = false, nullable = true, length = 36)
private String actcodeId;
@Formula("select COUNT(*) from school_info")
private int count;
@Temporal(TemporalType.TIMESTAMP)//不用set,hibernate会自动把当前时间写入
@Column(updatable = false, length = 20)
private Date createTime;
@Temporal(TemporalType.TIMESTAMP)
private Date updateTime;// 刚开始我默认insertable=false,但会读取出错提示如下:
// Value '0000-00-00' can not be represented as java.sql.Timestamp
// mappedBy="school"就相当于inverse=true,(mappedBy指定的是不需要维护关系的一端)
// 应该注意的是mappedBy值对应@ManyToOne标注的属性,我刚开始写成"schoolId",让我郁闷了好一会
@OneToMany(mappedBy = "school", cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = UserMember.class)
// 用范性的话,就不用targetEntity了
private List<usermember> users = </usermember>new ArrayList<usermember>(); </usermember>
}
@GeneratedValue(strategy=GenerationType.AUTO)我们常用的自增长机制,我这里采用的是hibernate的uuid生成机制.
需要注意的是import javax.xx.Entity ,而不是org.hibernate.xx.Entity。
郁闷的是我上面用到@Formula,生成的sql竟然是'select COUNT(*) from school_info as formula0_ from school_info schoolinfo0_,当然不能执行了,寻求正解中~!!!!!!!!!
UserMember.java(前面引入的包已经贴过了,下面就不贴了)
@Entity
@Table(name = "teacher_info")//实体类和数据库表名不一致时,才用这个
public class UserMember implements java.io.Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
@Column(updatable = false, nullable = false, length = 20)
private String logonName;
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false, length = 20)
private Date createTime;
@Temporal(TemporalType.TIMESTAMP)
private Date updateTime;
@ManyToOne(cascade = { CascadeType.MERGE })
@JoinColumn(name = "schoolId")
private SchoolInfo school;
//注意该类就不用声明schoolId属性了,如果不用@JoinColumn指明关联的字段,hibernate默认会是school_id.
}