0

我只是在处理@EmbededId 代码,我想在实体被持久化之前进行自动增量,这是不使用@GeneratedValue 和标识列的情况,

下面是具有复合 id 的表,

create table TBL_EMPLOYEE_002(
    ID integer, 
    COUNTRY varchar(50),
    NAME varchar(50),
    constraint PK_EMP_00240 primary key(ID,COUNTRY)
)

这是实体映射的代码,

@Entity
@Table(name="TBL_EMPLOYEE_002")
public class EmployeeEntitySix implements Serializable{

// contructor's

    @EmbeddedId    
    private EmployeeIdTwo id;

    @Column(name="NAME")
    private String employeeName;

// getters and setter's

    @PrePersist
    public void incId(){
        EntityManager em = null;
        Query q = null;
       EntityManagerFactory emf = null;
        try{
            emf = Persistence.createEntityManagerFactory("forPractise");
            em = emf.createEntityManager();
            q = em.createQuery("select max(e.id.employeeId) from EmployeeEntitySix e");
            List list = q.getResultList();
            Integer i = (list != null && list.size() > 0) ? Integer.valueOf(list.get(0).toString()) : 0;
            this.getId().setEmployeeId(++i);
        }catch(Exception e){
            System.out.println("EXCETION WHILE INCREASING COUNTER...");
            e.printStackTrace();
        }finally{
            if(em != null && em.isOpen()){
                em.close();
            }
            if(getEmf() != null && getEmf().isOpen()){
                getEmf().close();
            }
        }


}

这是复合id映射,

@Embeddable
public class EmployeeIdTwo implements Serializable{


    @Column(name="ID") 
    private Integer employeeId;

    @Column(name="COUNTRY",length=50)
    private String empCountry;

// getters and setters

    }

这段代码是我的主要方法,这个主要方法在其他类中,

public static void main(String [] args){
    EntityManagerFactory emf = null;
    EntityManager em = null;
    EntityTransaction tx = null;
    try{
        emf = Persistence.createEntityManagerFactory("forPractise");
        em = emf.createEntityManager();
        tx = em.getTransaction();            
        tx.begin();
    EmployeeEntitySix employee = new EmployeeEntitySix(new EmployeeIdTwo("ZIMBABWE"), "Henry Olanga");
    em.persist(employee);
....
}

现在上面的代码运行良好,每当我持久化实体“EmployeeEntitySix”时,使用@PerPersist注释的方法就会运行,它将首先获取最大id,递增它,将其设置为嵌入实体中的id并持久化实体。

现在我的问题是,

我创建了 EntityManagerFactory 两次,第一次是在 main 方法中,第二次是在实体 EmployeeEntitySix 的 @PrePersist 方法中。因此,我是否可以使用在实体 EmployeeEntitySix 的 main 方法中创建的第一个 Entitymanagerfactory 而预先持久化,或者我是否可以重用第一次在实体的 @PrePersist 方法的 main 方法中创建的 entitymanager。

仅供参考,我使用的是纯 Java 环境,我没有使用 Java EE 容器。

4

1 回答 1

1

Hibernate 默认尝试持久化实体类或嵌入 id 的所有字段,包括 field emf,但它不知道如何持久化 type 的字段EntityManagerFactory

当然,坚持一个EntityManagerFactory. 您可以将该字段标记为@Transient防止它被持久化,但是您将面临不同的问题。

EntityManagerFactory带有注解的注入@PersistenceUnit仅适用于在符合 Java EE 的应用服务器上运行的应用程序中的 CDI Bean 和 EJB。当您使用 main 方法时,我假设您的示例是一个简单的 JSE 程序。

此外,您不应EntityManager在生命周期回调方法中访问 s,例如@PrePersist. 引用 JPA 规范(JSR 317:JavaTM Persistence API,2.0 版):

通常,可移植应用程序的生命周期方法不应调用 EntityManager 或 Query 操作、访问其他实体实例或修改同一持久性上下文中的关系。生命周期回调方法可以修改调用它的实体的非关系状态。

我建议您不要使用EntityManagerFactory嵌入式 id 类,也不要使用incId-Method。相反,您可以employeeId在调用persist. 只要程序的一个实例与数据库一起工作,这就可以正常工作。当有多个程序尝试插入新员工时,可能会出现两个程序尝试插入相同 ID 的竞争条件。

为了防止这种情况,您可以使用数据库序列生成employeeId带有注释的@GeneratedValue, 和@SequenceGenerator. 您可以在此处找到有关 id 生成的更多信息:http ://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Sequencing

于 2013-04-05T12:08:16.717 回答