今天在做項目的時候遇到一個問題,同一個action里使用不同的操作(增刪改查)的時候總是獲得當前系統時間是同一個時間,后來檢查了下才知道是spring.xml里的action映射里沒有加scope="prototype"屬性 scope="prototype"沒寫的問題,項目中對一個表的增刪該操作是用一個action,這個action有add,update,delete,save這些方法,添加和修改是共用一個頁面,當頁面得到id時代表進行的修改操作,反之是添加操作。因為在配置spring的bean是忘了寫scope="prototype"所以每次添加時都顯示最后一次訪問過的記錄,找了很長時間,原來是spring bean出了問題。 scope="prototype" 會在該類型的對象被請求時創建一個新的action對象。如果沒有配置scope=prototype則添加的時候不會新建一個action,他任然會保留上次訪問的過記錄的信息
今天在做項目的時候遇到一個問題,同一個action里使用不同的操作(增刪改查)的時候總是獲得當前系統時間是同一個時間,后來檢查了下才知道是spring.xml里的action映射里沒有加scope="prototype"屬性 scope="prototype"沒寫的問題,項目中對一個表的增刪該操作是用一個action,這個action有add,update,delete,save這些方法,添加和修改是共用一個頁面,當頁面得到id時代表進行的修改操作,反之是添加操作。因為在配置spring的bean是忘了寫scope="prototype"所以每次添加時都顯示最后一次訪問過的記錄,找了很長時間,原來是spring bean出了問題。 scope="prototype" 會在該類型的對象被請求時創建一個新的action對象。如果沒有配置scope=prototype則添加的時候不會新建一個action,他任然會保留上次訪問的過記錄的信息
1.基本結構
CREATE OR REPLACE PROCEDURE 存儲過程名字
(
參數1 IN NUMBER,
參數2 IN NUMBER
) IS
變量1 INTEGER :=0;
變量2 DATE;
BEGIN
END 存儲過程名字
2.SELECT INTO STATEMENT
將select查詢的結果存入到變量中,可以同時將多個列存儲多個變量中,必須有一條
記錄,否則拋出異常(如果沒有記錄拋出NO_DATA_FOUND)
例子:
BEGIN
SELECT col1,col2 into 變量1,變量2 FROM typestruct where xxx;
EXCEPTION
WHEN NO_DATA_FOUND THEN
xxxx;
END;
...
3.IF 判斷
IF V_TEST=1 THEN
BEGIN
do something
END;
END IF;
4.while 循環
WHILE V_TEST=1 LOOP
BEGIN
XXXX
END;
END LOOP;
5.變量賦值
V_TEST := 123;
6.用for in 使用cursor
...
IS
CURSOR cur IS SELECT * FROM xxx;
BEGIN
FOR cur_result in cur LOOP
BEGIN
V_SUM :=cur_result.列名1+cur_result.列名2
END;
END LOOP;
END;
7.帶參數的cursor
CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
OPEN C_USER(變量值);
LOOP
FETCH C_USER INTO V_NAME;
EXIT FETCH C_USER%NOTFOUND;
do something
END LOOP;
CLOSE C_USER;
8.用pl/sql developer debug
連接數據庫后建立一個Test WINDOW
在窗口輸入調用SP的代碼,F9開始debug,CTRL+N單步調試
一對一(One-To-One)
使用@OneToOne注解建立實體Bean之間的一對一關聯。一對一關聯有三種情況:(1).關聯的實體都共享同樣的主鍵,(2).其中一個實體通過外鍵關聯到另一個實體的主鍵(注意要模擬一對一關聯必須在外鍵列上添加唯一約束),(3).通過關聯表來保存兩個實體之間的連接關系(要模擬一對一關聯必須在每一個外鍵上添加唯一約束)。
1.共享主鍵的一對一關聯映射:
@Entity
@Table(name="Test_Body")
public class Body {
private Integer id;
private Heart heart;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@OneToOne
@PrimaryKeyJoinColumn
public Heart getHeart() {
return heart;
}
public void setHeart(Heart heart) {
this.heart = heart;
}
}
@Entity
@Table(name="Test_Heart")
public class Heart {
private Integer id;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
通過@PrimaryKeyJoinColumn批注定義了一對一關聯
2.使用外鍵進行實體一對一關聯:
@Entity
@Table(name="Test_Trousers")
public class Trousers {
@Id
public Integer id;
@OneToOne
@JoinColumn(name = "zip_id")
public TrousersZip zip;
}
@Entity
@Table(name="Test_TrousersZip")
public class TrousersZip {
@Id
public Integer id;
@OneToOne(mappedBy = "zip")
public Trousers trousers;
}
上面的例子是指Trousers通過Trousers的外鍵列zip_id和TrousersZip關聯,@JoinColumn批注定義了聯接列,該批注和@Column批注有點類似,但是多了一個名為referencedColumnName的參數。該參數定義了所關聯目標實體中的聯接列,注意,當referencedColumnName關聯到非主鍵列的時候,關聯的目標類必須實現Serializable,還要注意的是所映像的屬性對應單個列(否則映射無效)
一對一關聯可能是雙向的,在雙向關聯中,有且僅有一端作為主體(owner)端存在:主體端負責維護聯接列(即更新),對于不需要維護這種關系的從表則通過mappedNy屬性進行聲明。mappedBy的值指向主體的關聯屬性。例子中,mappedBy的值為zip。最后,不必也不能再在被關聯端(ownedside)定義聯接列了,因為已經在主體端聲明了。
如果在主體沒有聲明@JoinColumn,系統自動進行處理:在主表(owner table)中將創建聯接列,列名為:主體的關聯屬性名+下劃線+被關聯端的主鍵列名。上面的例子中是zip_id,因為Trousers中的關聯屬性名為zip,TrousersZip的主鍵是id。
3.通過關聯表定義一對一關聯
@Entity
@Table(name="Test_People")
public class People {
@Id
public Integer id;
@OneToOne
@JoinTable(name ="TestPeoplePassports",
joinColumns = @JoinColumn(name="perple_fk"),
inverseJoinColumns = @JoinColumn(name="passport_fk")
)
public Passport passport;
}
@Entity
@Table(name="Test_Passport")
public class Passport {
@Id
public Integer id;
@OneToOne(mappedBy = "passport")
public People people;
}
People通過名為TestPeoplePassports的關聯表和Passport關聯。該關聯表擁有名為passport_fk的外鍵列,該外鍵指向Passport表,該信息定義為inverseJoinColoumns的屬性值,而people_fk外鍵列指向People表,該信息定義為joinColumns的屬性值。
這種關聯可能是雙向的,在雙向關聯中,有且僅有一端作為主體(owner)端存在:主體端負責維護聯接列(即更新),對于不需要維護這種關系的從表則通過mappedNy屬性進行聲明。mappedBy的值指向主體的關聯屬性。例子中,mappedBy的值為passport。最后,不必也不能再在被關聯端(ownedside)定義聯接列了,因為已經在主體端聲明了。
多對一(Many-to-One)
使用@ManyToOne批注來實現多對一關聯。
@ManyToOne批注有一個名為targetEntity的參數,該參數定義了目標實體名,通常不需要定義該參數,因為在大部分情況下默認值(表示關聯關系的屬性類型)就可以很好的滿足需求了。不過下面這種情況下這個參數就顯得有意義了:使用接口作為返回值而不是常見的實體。
@ManyToOne(targetEntity=CompanyImpl.class)
@JoinColoumn(name=”COPM_ID”)
Public Company getCompany(){
return company;
}
多對一的配置方式有兩種:(1)通過@JoinColoumn映像(2)通過關聯表的方式來映像
(1)通過@JoinColoumn映射
SRD Framework中Company,Category例子:
Company:
@ManyToOne
@JoinColumn(name = "CATEGORY_OPTION_ID")
private Category category = null;
Category:
@DiscriminatorValue("Category")
public class Category extends Option {
}
(2)通過關聯表映射
通過@JoinTable批注定義關聯表,該關聯表包含了指回實體表的外鍵(通過@JoinTable.joinColoumns)以及指向目標實體表的外鍵(通過@JoinTable.inverseJoinColoumns)
@Entity
@Table(name="Test_TreeType")
public class TreeType {
private Integer id;
private String name;
private ForestType forestType;
@ManyToOne(fetch = FetchType.LAZY)
@JoinTable(name="Test_Tree_Forest",
joinColumns = @JoinColumn(name="tree_id"),
inverseJoinColumns = @JoinColumn(name="forest_id") )
public ForestType getForestType() {// forestType的getter,setter方法必須在這里,否則會出錯
return forestType;
}
public void setForestType(ForestType forestType) {
this.forestType = forestType;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
@Table(name="Test_ForestType")
public class ForestType {
private Integer id;
private String name;
private Set<TreeType> trees;
@OneToMany(mappedBy="forestType")
public Set<TreeType> getTrees() {// trees的getter,setter方法必須在這里,否則會出錯
return trees;
}
public void setTrees(Set<TreeType> trees) {
this.trees = trees;
}
@Id @GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
一對多(One-to-Many)
使用@OneToMany批注可定義一對多關聯,一對多關聯可以是雙向關聯。
在EJB3規范中多對一這端幾乎總是雙向關聯中的主體(owner)端,而一對多這端關聯批注為@OneToMany(mappedBy...)
@Entity
Public class Troop{
@OneToMany(mappedBy=”troop”)
Public Set<Soldier> getSoldiers(){
......
}
@Entity
Public class Soldier{
@ManyToOne
@JoinColumn(name=”troop_fk”)
Public Troop getTroop(){
......
}
Troop通過troop屬性和Soldier建立一對多的雙向關聯,在mappedBy端不必也不能再定義任何物理映射。
對于一對多的雙向映射,如果要一對多這一端維護關聯關系,你需要刪除mappedBy元素并將多對一這端的@JoinColoumn的insertable和updatabel設置為false。這種方案不會得到什么明顯的優化,而且還會增加一些附加的UPDATE語句。
單向:
通過在被擁有的實體端(owned entity)增加一個外鍵列來實現一對多單向關聯是很少見的,也是不推薦的,建議通過一個聯接表來實現這種關聯(下面會講到)。
@JoinColoumn批注來描述這種單向關聯關系
@Entity
Public class Customer{
@OneToMany
@JoinColoumn(name=”CUST_ID”)
Public Set<ticket> getTickets() {
.....
}
@Entity
Public class Ticket{
...
}
Customer通過CUST_ID列和Ticket建立了單向關聯關系
通過關聯表處理單向關聯:
通過聯接表處理單向一對多關聯是首選方式,這種關聯通過@JoinTable批注進行描述
@Entity
Public class Trainer{
@OneToMany
@JoinTable(
name = "TrainedMonkeys",
jonColumns = {@JoinColumn(name="trainer_id"},
inverseJoinColumns = @JoinColumn(name = "monkey_id")
)
public Set<Monkey> getTrainedMonkeys() {
return trainedMonkeys;
}
......
}
@Entity
public class Monkey {
...//no bidir
}
上面這個例子中,Trainer通過TrainedMonkeys表和Monkey建立了單向關聯,其中外鍵trainer_id關聯到Trainer(joinColoumn),而外鍵monkey_id關聯到Monkey(inversejionColoumns)
默認處理機制:
通過聯接表來建立單向一對多關聯不需要描述任何物理映像,表名由以下三個部分組成:主表(ownertable)表名+從表(the other side table)表名,指向主表的外鍵名:主表表名+下劃線+主表主鍵列名,指向從表的外鍵名:主表所對應實體的屬性名+下劃線+從表主鍵列名,指向從表的外鍵定義為唯一約束,用來表示一對多的關聯關系。
@Entity
public class Trainer{
@OneToMany
Public Set<Tiger> getTrainedTigers(){
... ...
}
@Entity
public class Tiger{
.. ..//no bidir
}
上面這個例子中,Trainer和Tiger通過聯接表Trainer_Tiger建立單向關聯關系,其中外鍵trainer_id關聯到Trainer,而外鍵trainedTigers_id關聯到Tiger
5.1 一對一映射
雙向一對一關系需要在關系維護端(owner side)的one2one Annotition定義mappedBy屬性。建表時在關系被維護端(inverse side)建立外鍵列指向關系維護端的主鍵列。
假設Country 和 Capital 是雙向一對一的關系,具體元數據聲明如下:
public class Country {
@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country")
private Capital capital;
}
public class Capital {
@OneToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "id")
private Country country;
代碼中元數據的說明:
元數據描述:
@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country")
optional聲明關系是否是必須存在的,即是否允許其中一端為null。
cascade聲明級聯操作。
@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "id")
name聲明外鍵列的名字,referencedColumnName聲明外鍵指向列的列名。
5.2 一對多映射
雙向一對多關系,一是關系維護端(owner side),多是關系被維護端(inverse side)。 建表時在關系被維護端建立外鍵列指向關系維護端的主鍵列。
假設Father 和 Child 是雙向一對多的關系,具體元數據聲明如下:
public class Father {
@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")
public List<Child> getChildren() {
return children; }
}
public class Child {
@ManyToOne
@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")
public Father getFather() {
return father;
}
}
代碼中元數據的說明:元數據描述:
@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")
targetEntity = Child.class表明關系另一端的實體類型
cascade聲明級聯操作。
mappedBy聲明關系維護端的字段(field)名。
@ManyToOne
@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")
name聲明外鍵列的名字,referencedColumnName聲明外鍵指向列的列名。
5.3 多對多映射
多對多映射采取中間表連接的映射策略,建立的中間表將分別引入兩邊的主鍵作為外鍵。
EJB3對于中間表的元數據提供了可配置的方式,用戶可以自定義中間表的表名,列名。
假設Teacher 和 Student是多對多的關系,具體元數據聲明如下:
pubic class Teacher{
@ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)
@JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"),
joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))
public List<Student> getStudents() {
return students;
}
}
public class Student{
@ManyToMany(targetEntity = Teacher.class, mappedBy = "students")
public List<Teacher> getTeachers() {
return teachers; }
}
代碼中元數據的說明:
元數據描述:
@ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)
targetEntity = Student.class表明關系另一端的實體類型。cascade聲明級聯操作。
@JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"),
joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))
JoinTable配置中間表信息,它由3個部分組成:
1) table = @Table(name = "M2M_TEACHER_STUDENT") ,聲明中間表的名字
2) joinColumns ,定義中間表與關系維護端的外鍵關系。
3) inverseJoinColumns,定義中間表與inverse端的外鍵關系.
本文來自CSDN博客,出處:http://blog.csdn.net/senton/archive/2007/03/15/1529969.aspx
1.設置Pojo為實體
01.@Entity //標識這個pojo是一個jpa實體
02.public class Users implements Serializable {
03.}
2.設置表名
01.@Entity
02.@Table(name = "users") //指定表名為users
03.public class Users implements Serializable {
04.}
3.設置主鍵
01.public class Users implements Serializable {
02.@Id
03.private String userCode;
4. 設置字段類型
通過@Column注解設置,包含的設置如下
.name:字段名
.unique:是否唯一
.nullable:是否可以為空
.inserttable:是否可以插入
.updateable:是否可以更新
.columnDefinition: 定義建表時創建此列的DDL
.secondaryTable: 從表名。如果此列不建在主表上(默認建在主表),該屬性定義該列所在從表的名字。
01.@Column(name = "user_code", nullable = false, length=32)//設置屬性userCode對應的字段為user_code,長度為32,非空
02.private String userCode;
03.@Column(name = "user_wages", nullable = true, precision=12, scale=2)//設置屬性wages對應的字段為user_wages,12位數字可保留兩位小數,可以為空
04.private double wages;
05.@Temporal(TemporalType.DATE)//設置為時間類型
06.private Date joinDate;
5.字段排序
在加載數據的時候可以為其指定順序,使用@OrderBy注解實現
01.@Table(name = "USERS")
02.public class User {
03.@OrderBy(name = "group_name ASC, name DESC")
04.private List books = new ArrayList();
05.}
6.主鍵生成策略
01.public class Users implements Serializable {
02.@Id
03.@GeneratedValue(strategy=GenerationType.IDENTITY)//主鍵自增,注意,這種方式依賴于具體的數據庫,如果數據庫不支持自增主鍵,那么這個類型是沒法用的
04.@Column(name = "user_id", nullable = false)
05.private int userId;
06.
07.
08.public class Users implements Serializable {
09.@Id
10.@GeneratedValue(strategy=GenerationType.TABLE)//通過一個表來實現主鍵id的自增,這種方式不依賴于具體的數據庫,可以解決數據遷移的問題
11.@Column(name = "user_code", nullable = false)
12.private String userCode;
13.
14.
15.public class Users implements Serializable {
16.@Id
17.@GeneratedValue(strategy=GenerationType.SEQUENCE)//通過Sequence來實現表主鍵自增,這種方式依賴于數據庫是否有SEQUENCE,如果沒有就不能用
18.@SequenceGenerator(name="seq_user")
19.@Column(name = "user_id", nullable = false)
20.private int userId;
7.一對多映射關系
有T_One和T_Many兩個表,他們是一對多的關系,注解范例如下
主Pojo
01.@Entity
02.@Table(name = "T_ONE")
03.public class One implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "ONE_ID", nullable = false)
07.private String oneId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.@OneToMany(cascade = CascadeType.ALL, mappedBy = "oneId")//指向多的那方的pojo的關聯外鍵字段
11.private Collection<Many> manyCollection;
子Pojo
01.@Entity
02.@Table(name = "T_MANY")
03.public class Many implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "MANY_ID", nullable = false)
07.private String manyId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.
11.@JoinColumn(name = "ONE_ID", referencedColumnName = "ONE_ID")//設置對應數據表的列名和引用的數據表的列名
12.@ManyToOne//設置在“一方”pojo的外鍵字段上
13.private One oneId;
8.多對多映射關系
貌似多對多關系不需要設置級聯,以前用hibernate的時候著實為多對多的級聯頭疼了一陣子,JPA的多對多還需要實際的嘗試一下才能有所體會。
估計JPA的多對多也是可以轉換成兩個一對多的。
第一個Pojo
01.@Entity
02.@Table(name = "T_MANYA")
03.public class ManyA implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "MANYA_ID", nullable = false)
07.private String manyaId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.@ManyToMany
11.@JoinTable(name = "TMANY1_TMANY2", joinColumns = {@JoinColumn(name = "MANYA_ID", referencedColumnName = "MANYA_ID")}, inverseJoinColumns = {@JoinColumn(name = "MANYB_ID", referencedColumnName = "MANYB_ID")})
12.private Collection<ManyB> manybIdCollection;
第二個Pojo
01.@Entity
02.@Table(name = "T_MANYB")
03.public class ManyB implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "MANYB_ID", nullable = false)
07.private String manybId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.@ManyToMany(mappedBy = "manybIdCollection")
11.private Collection<ManyA> manyaIdCollection;
9.一對一映射關系
主Pojo
01.@Entity
02.@Table(name = "T_ONEA")
03.public class OneA implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "ONEA_ID", nullable = false)
07.private String oneaId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.@OneToOne(cascade = CascadeType.ALL, mappedBy = "oneA")//主Pojo這方的設置比較簡單,只要設置好級聯和映射到從Pojo的外鍵就可以了。
11.private OneB oneB;
從Pojo
01.@Entity
02.@Table(name = "T_ONEB")
03.public class OneB implements Serializable {
04.private static final long serialVersionUID = 1L;
05.@Id
06.@Column(name = "ONEA_ID", nullable = false)
07.private String oneaId;
08.@Column(name = "DESCRIPTION")
09.private String description;
10.@JoinColumn(name = "ONEA_ID", referencedColumnName = "ONEA_ID", insertable = false, updatable = false)//設置從方指向主方的關聯外鍵,這個ONEA_ID其實是表T_ONEA的主鍵
11.@OneToOne
12.private OneA oneA;
10 大字段
01.@Lob //對應Blob字段類型
02.@Column(name = "PHOTO")
03.private Serializable photo;
04.@Lob //對應Clob字段類型
05.@Column(name = "DESCRIPTION")
06.private String description;
11.瞬時字段
不需要與數據庫映射的字段,在保存的時候不需要保存倒數據庫
01.@Transient
02.private int tempValue;
03.
04.public int getTempValue(){
05.get tempValue;
06.}
07.
08.public void setTempValue(int value){
09.this.tempValue = value;
10.}