2015-02-05 18 views
14

yay çizme ve yay veri JPA ile yüklendiğinde UUID yerine bir dizeye bir ikili aktarmak için JPA 2.1 Converter yüklenmemesi zaman/tarih işleme için biraz daha var) bir kitaplık .jar dosyasında bulunur.hazırda Özel bir dönüştürücü var

Daha sonra bir .jar dosyasında varlıklarım var. Bunun gibi:

package de.kaiserpfalzEdv.office.core.security; 

import de.kaiserpfalzEdv.commons.jee.db.OffsetDateTimeJPAConverter; 
import de.kaiserpfalzEdv.commons.jee.db.UUIDJPAConverter; 
import org.apache.commons.lang3.builder.EqualsBuilder; 
import org.apache.commons.lang3.builder.HashCodeBuilder; 
import org.apache.commons.lang3.builder.ToStringBuilder; 
import org.apache.commons.lang3.builder.ToStringStyle; 

import javax.persistence.Column; 
import javax.persistence.Convert; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 
import javax.validation.constraints.NotNull; 
import java.io.Serializable; 
import java.time.OffsetDateTime; 
import java.time.ZoneId; 
import java.util.Collections; 
import java.util.HashSet; 
import java.util.Set; 
import java.util.UUID; 

@Entity 
@Table(
     name = "tickets" 
) 
public class SecurityTicket implements Serializable { 
    private final static ZoneId TIMEZONE = ZoneId.of("UTC"); 
    private final static long DEFAULT_TTL = 600L; 
    private final static long DEFAULT_RENEWAL = 600L; 

    @Id @NotNull 
    @Column(name = "id_", length=50, nullable = false, updatable = false, unique = true) 
    @Convert(converter = UUIDJPAConverter.class) 
    private UUID id; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "account_id_", nullable = false, updatable = false, unique = true) 
    private Account account; 

    @Convert(converter = OffsetDateTimeJPAConverter.class) 
    @Column(name = "created_", nullable = false, updatable = false) 
    private OffsetDateTime created; 

    @Convert(converter = OffsetDateTimeJPAConverter.class) 
    @Column(name = "validity_", nullable = false, updatable = false) 
    private OffsetDateTime validity; 


    @Deprecated 
    public SecurityTicket() { 
    } 


    public SecurityTicket(@NotNull final Account account) { 
     id = UUID.randomUUID(); 
     this.account = account; 
     created = OffsetDateTime.now(TIMEZONE); 
     validity = created.plusSeconds(DEFAULT_TTL); 
    } 


    public void renew() { 
     validity = OffsetDateTime.now(TIMEZONE).plusSeconds(DEFAULT_RENEWAL); 
    } 

    public boolean isValid() { 
     OffsetDateTime now = OffsetDateTime.now(TIMEZONE); 

     System.out.println(validity.toString() + " is hopefully after " + now.toString()); 

     return validity.isAfter(now); 
    } 

    public UUID getId() { 
     return id; 
    } 

    public OffsetDateTime getValidity() { 
     return validity; 
    } 

    public String getAccountName() { 
     return account.getAccountName(); 
    } 

    public String getDisplayName() { 
     return account.getDisplayName(); 
    } 

    public Set<String> getRoles() { 
     HashSet<String> result = new HashSet<>(); 

     account.getRoles().forEach(t -> result.add(t.getDisplayNumber())); 

     return Collections.unmodifiableSet(result); 
    } 

    public Set<String> getEntitlements() { 
     return Collections.unmodifiableSet(new HashSet<>()); 
    } 


    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (obj == this) { 
      return true; 
     } 
     if (obj.getClass() != getClass()) { 
      return false; 
     } 
     SecurityTicket rhs = (SecurityTicket) obj; 
     return new EqualsBuilder() 
       .append(this.id, rhs.id) 
       .isEquals(); 
    } 

    @Override 
    public int hashCode() { 
     return new HashCodeBuilder() 
       .append(id) 
       .toHashCode(); 
    } 


    @Override 
    public String toString() { 
     return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 
       .append("id", id) 

       .append("account", account) 
       .append("validity", validity) 
       .toString(); 
    } 
} 

Uyumluluk testleri maven ve testng ile çalışırken veritabanı oldukça iyi çalışıyor.

Caused by: org.hibernate.HibernateException: Wrong column type in kpoffice.tickets for column id_. Found: varchar, expected: binary(50) 
     at org.hibernate.mapping.Table.validateColumns(Table.java:372) 
     at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1338) 
     at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:175) 
     at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:525) 
     at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859) 
     at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852) 
     at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:845) 
     at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398) 
     at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844) 
     at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) 
     at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343) 
     at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562) 
     ... 120 more 

dönüştürün Otomatik Devreye Giren çalışmaz: Uygulamayı (üçüncü .jar dosyası) başladığı zaman, ben aşağı kaynar kötü istisna olsun. Dönüştürücüyü sınıfa ve özniteliğe açıklama yapmayı denedim. Ama dönüştürücü kullanılmıyor. Ancak hazırda bekleyen UUID türünü hazırda belirli bir açıklama ile eklediğimde, aynı özellik için bir dönüştürücü ve hazırda beklemede bir tür tanımlamaya sahip olmadı. Yani hazırda bekletici yapılandırmayı okur.

Envers kullanıldığında, JPA 2.1 dönüştürücü çalışmaz. Ama yazılımlarımı kullanmam. spec Okuma

Ben orada yanlış yapıyorum bilen biri var umut ...

+6

JPA spesifikasyonu, dönüşümün bir öğenin id özelliğine uygulanmayacağını açıkça belirtir. Belki de JPA dönüşüm ek açıklamalarınızı kaldırabilir ve yerine Hazırda Bekleme özel bir yaklaşım kullanarak deneyebilirsiniz? –

+0

http://stackoverflow.com/questions/39547615/convert-in-hibernate-not-working-with-spring-4-java-lang-nosuchmethoderror-org/39551331#39551331 –

cevap

10

Andy Wilkinson gave the correct answer. kez bir çok yardımcı olur.

JPA 2.1 Dönüştürücüler, @Id ek açıklamalı özniteliklere uygulanmaz.

Teşekkür ederim Andy.

+0

[JSR-000338 JavaTM Persistence 2.1] (https://jcp.org/aboutJava/communityprocess/final/jsr338/index.html) bölüm 11.1.10 Convert Annotation, _The Convert notu, aşağıdakilerin dönüşümünü belirtmek için kullanılmamalıdır: ** Id öznitelikleri ** (gömülü ids ve türetilmiş özniteliklerin öznitelikleri dahil), sürüm öznitelikleri, ilişki öznitelikleri ve –

+0

http: //www.nailedtothex.org/roller/kyle/entry/using-jpa-2-1-attributeconverter, dönüştürücüler EmbeededId ile çalışmalıdır. Ancak, benim durumumda, aynı zamanda başarısız: https://stackoverflow.com/questions/48188365/hibernate-no-type-name-with-attributeconverter-on-map Herhangi bir öneriniz var mı? – nimo23

+0

Özellikler'i (Tom tarafından alıntılanan) okursanız, teknik özelliklerin gömülü bir kimliğin özelliklerini içermediğini görürsünüz. Yani eğer işe yaradıysa, bu güvenmemelisiniz, özel bir uzantıdır. – klenkes74

0

Başka bir seçenek şöyle, alternatif getters/ayarlayıcıları dönüşüm mantığını gömmek için geçerli:

public class SecurityTicket implements Serializable 
{ 
... 
private UUID id; 

@Transient 
public UUID getUUID() 
{ 
    return id; 
} 

@Id @NotNull 
@Column(name = "id_", length=50, nullable = false, updatable = false, unique = true) 
public String getID() 
{ 
    return id.toString(); 
} 

public void setUUID(UUID id) 
{ 
    this.id = id; 
} 

public void setID(String id) 
{ 
    this.id = UUID.fromString(id); 
} 

... 

@Transient açıklama ayrı bir UUID özellik olduğunu düşünüyorum gelmez bu nedenle bu gaz giderici görmezden JPA söyleyecektir. Kendini savunmasız, ama benim için bir UUID PK ile sınıfları üzerinde JPA kullanarak çalıştı. SetId (String) yöntemiyle hatalı değer ayarlayan diğer kodların riskini çalıştırıyorsunuz, ancak tek çözüm görünüyor. Bu yöntemin korunması/özel olması mümkün olabilir mi?

Normal Java kodu, farklı argüman türlerine göre aynı ada sahip ayarlayıcıları ayırt edebilecek olsa da, JPA bunları farklı şekilde adlandırmazsanız şikayet edecektir.

JPA'nın, Dönüştürücüleri Ids üzerinde desteklememesi veya standart dönüştürme yöntemleriyle (örn. ToString/fromString, intValue/parseInt, vb.) Sınıflar için dönüştürücüler gerektirmemesi JAXB kuralına uymaması can sıkıcıdır.