代码之家  ›  专栏  ›  技术社区  ›  sinuhepop

使用EclipseLink和Querydsl自定义数据类型

  •  10
  • sinuhepop  · 技术社区  · 12 年前

    我创建了一个自定义数据类型,用于存储有效且规范化的电子邮件地址:

    public class Email implements Serializable {
    
        private final String value;
    
        public Email(String emailAddress) {
            this.value = normalize(emailAddress);
            if (!isValid(value)) {
                throw new IllegalArgumentException("Email address format is not valid: " + value);
            }
        }
        ...
    }
    

    以及相应的JPA 2.1转换器,用于自动存储到数据库和从数据库中检索:

    @Converter(autoApply = true)
    public class EmailConverter implements AttributeConverter<Email, String> {
    
        @Override
        public String convertToDatabaseColumn(Email email) {
            return email == null ? null : email.toString();
        }
    
        @Override
        public Email convertToEntityAttribute(String email) {
            return email == null ? null : new Email(email);
        }
    
    }
    

    现在,我可以将其用作个人实体的财产:

    public class Person extends BaseEntity {
    
        private String name;
    
        private LocalDate birthDate;
    
        @QueryType(PropertyType.STRING)
        private Email email;
    
        ...
    }
    

    这非常有效。但当我试图使用Querydsl通过电子邮件地址的开头找到所有人时,我遇到了一个问题。我用注释了电子邮件属性 @QueryType 作为字符串。通过这种方式,创建了Querydsl元模型,这样我就可以进行查询(使用 .startsWith() )像这样:

    private static final QPerson person = QPerson.person;
    
    public List<Person> getEmailStartWith(String pattern) {
        pattern = Email.normalize(pattern);
        return new JPAQuery(getEntityManager())
            .from(person)
            .where(person.email.startsWith(pattern))
            .orderBy(person.email.asc())
            .list(person);
    }
    

    但当我运行它时,我会得到这个异常:

    java.lang.IllegalArgumentException: You have attempted to set a value of type class java.lang.String for parameter 1 with expected type of class xxx.Email from query string select person
    from Person person
    where person.email like ?1 escape '!'
    order by person.email asc.
    at org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:932) ~[eclipselink-2.5.0.jar:2.5.0.v20130507-3faac2b]
    at org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:906) ~[eclipselink-2.5.0.jar:2.5.0.v20130507-3faac2b]
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:469) ~[eclipselink-2.5.0.jar:2.5.0.v20130507-3faac2b]
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:1) ~[eclipselink-2.5.0.jar:2.5.0.v20130507-3faac2b]
    at com.mysema.query.jpa.impl.JPAUtil.setConstants(JPAUtil.java:44) ~[querydsl-jpa-3.2.1.jar:na]
    at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:130) ~[querydsl-jpa-3.2.1.jar:na]
    at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:97) ~[querydsl-jpa-3.2.1.jar:na]
    at com.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:240) ~[querydsl-jpa-3.2.1.jar:na]
    ...
    

    我可以使用JPQL得到正确的结果(还有一个不雅的技巧, concat ):

    public List<Person> getEmailStartWith(String pattern) {
        pattern = Email.normalize(pattern);
        return getEntityManager()
            .createQuery("select p from Person p where p.email like concat(?1, '%')", Person.class)
            .setParameter(1, pattern)
            .getResultList();
    }
    

    但我当然更喜欢Querydsl的类型安全性。是否可以使用此库创建此查询?

    1 回复  |  直到 10 年前
        1
  •  1
  •   Community CDub    8 年前

    根据 查询dsl 造物主, Timo Westkämper issue 更多地与 Eclipse链接 .