2012-10-05 47 views
5

Tengo un nuevo objeto. Quiero saber la id antes de guardarla. ¿Es posible? O hay otra forma de esto? Estoy usando jpa como orm y oráculo como base de datos.¿Cómo sé el ID antes de guardar un objeto en jpa

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

Tengo un campo de código en mi entidad. Si el usuario no ingresa un valor para el campo code, quiero establecer el código como id de la entidad. Si persisto entidad, por supuesto puedo obtener ID y establecer el valor del código como id, pero esta es una base de datos de consulta adicional.

Quiero hacer algo así

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

Se podría evitar la @GeneratedValue, utilizar el generador de sí mismo para obtener el valor y la puso a la entidad "manualmente" yo no – SJuan76

+0

Quiero configurarlo manualmente. Si recibo el siguiente valor de id de Oracle y lo configuro para la identificación de la nueva entidad, ¿es racional? – mstzn

Respuesta

5

Después de una larga investigación sobre esto, finalmente encontré una solución.

De hecho, si se utiliza generador de secuencia de en JPA, sin duda no se puede obtener la Identificación de la entidad antes de guardarla en la base de datos, porque el próximo ID será asignado por la secuencia de bases de datos.

hay una manera de obtener el identificador de si se utiliza un generador personalizado , se puede obtener el ID antes de guardar.Aquí es sencilla aplicación:

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

Usando CustomGenerator de campo id:

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8

con un identificador de tipo @GeneratedValue no se puede saber que el valor de antemano (antes de que realmente escribirlo). Sin embargo, una vez que persista su Bean, el campo id se rellenará en esa instancia de bean y podrá obtenerlo sin necesidad de realizar una consulta adicional. En otras palabras:

MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

También, dependiendo de cómo esté configurado el EntityManager, es posible que deba también el primer confirmar la transacción (manualmente) antes de poder obtener ese id.

actualización según comentario

Si desea interceptar y hacer algo a la entidad antes de que se guarda y/o actualizado, puede utilizar oyentes LifeCycle JPA (si está utilizando la versión APP 2): Handling JPA lifecycle event using listeners and callbacks .

Básicamente se puede realizar un método validate() en su frijol, anotar con @PrePersist y @PreUpdate y hacer la validación en el mismo (si el código es conjunto vacío al valor de ID)

actualización por segundo comentario

Sí, honestamente pensé en eso hace un momento: que si el ID se genera automáticamente, podría llenarse DESPUÉS del evento de pre-persistencia, de modo que cuando se ejecuta el código de pre-persistencia, aún no se sabe cuál es el ID (También puede observar que en el ejemplo, el enlace al ID NO está autogenerado, sino que se establece manualmente). Lo que puede hacer en este caso es agregar un campo booleano a su entidad (anotado con @Transient para que no se conserve) llamado isCodeEmpty (que es falso de manera predeterminada si no se ha inicializado específicamente). Luego, en su método anotado @PrePersist, comprueba si el valor para el campo de código está vacío y, de ser así, establezca booleano en verdadero. A continuación, refactorizar el método setId(...) tal que (aparte de establecer el campo id) se comprobará este Booleano, y si se ha ajustado verdad el valor del campo de código a la del campo id:

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

Gracias por responder. Actualicé mi pregunta. ¿Puedes verificarlo? – mstzn

+0

He intentado la entidad listener.but en prepersist id value is null.I no sabe por qué es nulo.I implementa así = http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htm tiene usted sugerencia o idea? Muchas gracias – mstzn

+1

su idea es excelente pero después de que el método prePersist setId() no funcionara. Hice lo que usted dice. Lo estoy depurando, pero el método setId no se ejecutó y el campo de código no se configuró. Prepersist está funcionando. – mstzn

Cuestiones relacionadas