【问题标题】:CDI Inject Class in JPA Converter (EclipseLink)JPA 转换器中的 CDI 注入类 (EclipseLink)
【发布时间】:2015-09-17 15:41:12
【问题描述】:

我有一个问题,可以在 JPA 转换中使用 java CDI 吗?

我正在做一些测试来研究,但我无法在我的转换器中注入对象:

我正在使用eclipseLink,请看我的代码,请分析我的代码哪里出错了?我怎样才能以最好的方式做到这一点?

基本上为了更好地理解,我将有一个代表我的用户登录的会话 Bean,这个会话 Bean 我有用户时区,我想在我的转换器中注入这个时区以将数据写入数据库中的 UTC

我的代码:

JPA 转换器: org.eclipse.persistence.mappings.converters.Converter

package joda;

import inject.qualifier.UserTimeZoneQualifier;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import enumerator.UserType;
import security.UserSession;

@RequestScoped
public class JodaDateTimeUTCConverter implements Converter {
private static final long serialVersionUID = 1L;

// JUST TEST IT'S WAS INJECT AND REMOVE
private UserSession userSession = new UserSession("America/Mexico_City", UserType.HIGH_HISK);

@Inject
@UserTimeZoneQualifier
String userTimeZone;

//TODO FOR TEST
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss:SSS - z - ZZZZZZZZZZZZZZZZZZ");
SimpleDateFormat dt = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss:SSS - z - ZZZZZZZZZZZZZZZZZZ"); 

@Override
public Object convertDataValueToObjectValue(Object dataValue, Session session) {
    // TODO REMOVE
    DateTimeZone timeZone = DateTimeZone.forID(userSession.getTimeZoneLocale());
    System.out.println("BEFORE OF CONVERTION : " + dt.format(dataValue));
    System.out.println("AFTER  OF CONVERTION : " + dtf.print(new DateTime((Timestamp) dataValue).withZone(timeZone)));
    System.out.println("userTimeZone INJECT" + userTimeZone);


    return dataValue instanceof Date ? new DateTime((Timestamp) dataValue).withZone(timeZone) : null;

}

@Override
public Object convertObjectValueToDataValue(Object objectValue, Session session) {

    System.out.println("GO TO DB(DATAVALUE)");
    System.out.println("AFTER  OF CONVERTION : " + dtf.print(((DateTime) objectValue).withZone(DateTimeZone.UTC)));

    return objectValue instanceof DateTime?((DateTime) objectValue).withZone(DateTimeZone.UTC).toLocalDateTime().toDate() : null;
}

@Override
public void initialize(DatabaseMapping mapping, Session session) {
}

@Override
public boolean isMutable() {
    return false;
}

public String getUserTimeZone() {
    return userTimeZone;
}

public void setUserTimeZone(String userTimeZone) {
    this.userTimeZone = userTimeZone;
}
}

我的@UserTimeZoneQualifier:

package inject.qualifier;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD, METHOD, TYPE, PARAMETER})
public @interface UserTimeZoneQualifier {

}

还有我的 UserSessionProduce:

package inject;

import inject.qualifier.UserTimeZoneQualifier;

import javax.annotation.PostConstruct;
import javax.enterprise.inject.Produces;

import enumerator.UserType;
import security.UserSession;

public class UserSessionProduce {

private UserSession userSession;

@PostConstruct
public void init(){
    this.userSession = new UserSession("America/Mexico_City", UserType.ADMINISTRATOR);
}

@Produces
public UserSession getUserSessionInstance(){
    return this.userSession;
}

@Produces
@UserTimeZoneQualifier
public String getUserSessionTimeZone(){
    return this.userSession.getTimeZoneLocale();
}

@Produces
public UserType getUserType(){
    return this.userSession.getUserType();
}
}

注意:除了注入到转换器之外,所有其他功能都运行良好,我可以弹出 EntityManager 和其他类以及将数据持久化到数据库中

【问题讨论】:

    标签: java jpa eclipselink converter cdi


    【解决方案1】:

    很遗憾,你不能。该规范要求在 EntityListener 实现中支持 CDI 注入。它不适用于转换器。

    如果您想访问您的注入点,您可以使用CDI.current() 来访问CDI<Object> 实例。使用它就像使用 Instance<Object> 一样 - 您可以执行 .select(qualifier).select(clazz).get() 之类的操作来检索 bean 实例。

    如果你需要使用限定符,你首先需要一个文字。

    public class UserTimeZoneQualifierLiteral extends AnnotationLiteral<UserTimeZoneQualifier> implements UserTimeZoneQualifier {
    
    }
    

    然后实例化

    UserTimeZoneQualifier qualifier = new UserTimeZoneQualifier(); // or use a singleton here.
    

    【讨论】:

    • 你能指导我做我想做的事吗?我如何使用登录的用户时区来转换或 JPA 实体?非常感谢您的高级支持
    • 我刚刚在我的答案中添加了一些信息,如果有帮助请告诉我。
    • 完美我测试:String userTimeZone = javax.enterprise.inject.spi.CDI.current().select(UserSession.class).get().getTimeZoneLocale(); 并且它有效,我无法使用限定符,你有一个例子吗?我必须做一些扩展 AnnotationLiteral 类的类?
    • 是的,你需要一个注解文字。我很快就会回答。
    • 感谢@John Ament 的所有支持和关注
    猜你喜欢
    • 2021-12-23
    • 2016-06-07
    • 1970-01-01
    • 2013-08-29
    • 2011-03-15
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多