我利用:
NetBeans IDE 6.7.1, GlassFish v2.1, Oracle 10g XE, JAVA 6 SE, JAVA 5 EE,
从无状态EJB内部我持有类型为customer的实体我有注释: 类客户中的@SequenceGenerator(name =“seq”,sequenceName =“cust_id_seq”)所以 主键是从序列cust_id_seq在数据库中自动生成的,但是当我坚持第一个客户时,主键是9951而不是10000,第二个客户的主键是9952.在我坚持两个客户之后,GlassFish v2.1的输出是:
应用程序服务器启动完成。
我的身份是:0
TopLink,版本:Oracle TopLink Essentials - 2.1(Build b31g-fcs(10/19/2009))
服务器:未知 file:/ C:/ Documents%20and%20Settings / IOANNIS_PAPAIOANNOU / My%20Documents / NetBeansProjects / VideoClub / dist / gfdeploy / VideoClub-ejb_jar / -vc_pu login successfully
我的身份是:9951
我的身份是:0
我的身份是:9952
@Entity
@Table(name = "customer")
@SequenceGenerator(name="seq", sequenceName="cust_id_seq")
public class Customer implements Serializable
{
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
@Column(name="CUST_ID")
private int id;
@Column(name = "phone_number")
private int phoneNumber;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "credit")
private int credit;
@OneToMany
private Collection<CustRentMovie> rents = new ArrayList<CustRentMovie>();
public int getCredit()
{
return credit;
}
public void setCredit(int credit)
{
this.credit = credit;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
public int getPhoneNumber()
{
return phoneNumber;
}
public void setPhoneNumber(int phoneNumber)
{
this.phoneNumber = phoneNumber;
}
public Collection<CustRentMovie> getRents()
{
return rents;
}
public void setRents(Collection<CustRentMovie> rents)
{
this.rents = rents;
}
}
EJB的代码:
@Stateless
public class ClerkSessionBean implements ClerkSessionRemote
{
@PersistenceContext(unitName = "vc_pu")
private EntityManager em;
public int writeCustomer(AlmostCustomer almostCustomer)
{
Customer customer = new Customer();
System.out.println("My id is: " + customer.getId());
customer.setFirstName(almostCustomer.getFirstName());
customer.setLastName(almostCustomer.getLastName());
customer.setPhoneNumber(almostCustomer.getPhoneNumber());
em.persist(customer);
System.out.println("My id is: " + customer.getId());
return customer.getId();
}
}
创建数据库的脚本的一部分:
CREATE table customer
(
cust_id NUMBER(5),
phone_number NUMBER(10) NOT NULL,
first_name VARCHAR2(12) NOT NULL,
last_name VARCHAR2(30) NOT NULL,
-- Τα χρήματα που έχει ένας πελάτης στο λογαριασμό του.
credit NUMBER(5, 2) DEFAULT 0 NOT NULL,
CONSTRAINT cust_pk PRIMARY KEY (cust_id),
-- Μόνο ένας λογαριασμός για κάθε σπίτι.
CONSTRAINT phone_unique UNIQUE (phone_number)
)
/
DROP SEQUENCE cust_id_seq
/
CREATE SEQUENCE cust_id_seq MINVALUE 10000 MAXVALUE 99999 INCREMENT BY 1 START WITH 10000 NOCACHE NOCYCLE ORDER
/
Yiannis P。
答案 0 :(得分:3)
我认为您应该将CREATE SEQUENCE cust_id_seq ... INCREMENT BY
1
更改为... INCREMENT BY
50
。这就是原因。
声明的序列增量应与@SequenceGenerator
的{{1}}参数匹配。未指定allocationSize
,因此默认为50.但真实allocationSize
仅为1,而不是50.因此INCREMENT BY
与真实allocationSize
之间存在不匹配。< / p>
以下是这种不匹配可能导致问题的原因。 TopLink Essentials(TLE)在INCREMENT BY
上调用NEXTVAL()
。序列返回10000 + 1.TLE假设序列仅增加50(默认JPA cust_id_seq
)而不是1(实际数量)。 TLE从10001中减去allocationSize
= 50,得到9951。
顺便说一句,如果您有这样做的自由,请考虑升级到TLE的继任者EclipseLink(和Glassfish v3)。
答案 1 :(得分:0)