(playframework 2.0.2-java) EBean - No ScalarType registered error when querying with enum values

匿名 (未验证) 提交于 2019-12-03 09:19:38

问题:

I have Role entity class:

@Entity public class Role extends Model {      @Id     @Constraints.Required     public Integer id;      @Constraints.Required     @Formats.NonEmpty     @Enumerated(EnumType.STRING)     public RoleNameEnum name; // name is enum value } 

In some test I try to find users by role:

List<User> users = User.findByRole(Role.findByRoleName(RoleNameEnum.ADMIN)); 

where method findByRoleName() is following:

public static List<User> findByRole(Role role) {     return find.where().eq("role", role).findList(); } 

I receive error:

[error] Test UserTest.findUsersByRole failed: No ScalarType registered for class models.Role [error]     at com.avaje.ebeaninternal.server.persist.Binder.bindObject(Binder.java:183) [error]     at com.avaje.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:162) [error]     at com.avaje.ebeaninternal.server.query.CQuery.prepareBindExecuteQuery(CQuery.java:413) [error]     at com.avaje.ebeaninternal.server.query.CQueryEngine.findMany(CQueryEngine.java:198) [error]     at com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine.findMany(DefaultOrmQueryEngine.java:104) [error]     at com.avaje.ebeaninternal.server.core.OrmQueryRequest.findList(OrmQueryRequest.java:344) [error]     at com.avaje.ebeaninternal.server.core.DefaultServer.findList(DefaultServer.java:1469) [error]     at com.avaje.ebeaninternal.server.querydefn.DefaultOrmQuery.findList(DefaultOrmQuery.java:906) [error]     at com.avaje.ebeaninternal.util.DefaultExpressionList.findList(DefaultExpressionList.java:201) [error]     at models.User.findByRole(User.java:63) [error]     at UserTest$4.run(UserTest.java:62) [error]     at play.test.Helpers.running(Helpers.java:294) [error]     at UserTest.findUsersByRole(UserTest.java:58) 

Does anybody have an idea what might be a problem?

回答1:

The quickest solution, assuming that you are mapping EnumValue exactly the same as the enum names:

public enum RoleNameEnum {     @EnumValue("REGULAR")     REGULAR,     @EnumValue("ADMIN")     ADMIN } 

Then you can implement the findByRole method as following:

public static List<User> findByRole(Role role) {     return find.where().eq("role", role.name()).findList(); } 

where the magic is just using the mapped string value instead of the enum instance for the role name.

I posted a bug on the ebean issue tracker: http://www.avaje.org/bugdetail-427.html, binder should detect the enum object and interpret it as its mapped value automatically.

EDIT:

In case that you need some other mapping than the simple enum value, here it is the utility code to get the value set using the @EnumValue annotation

public static <T extends Enum<T>> String serialize(T theEnum) {     try {         for (Field f : theEnum.getDeclaringClass().getDeclaredFields()) {             if (theEnum.equals(f.get(theEnum))) {                 EnumValue enumValue = f.getAnnotation(EnumValue.class);                 if (enumValue != null)                     return enumValue.value();             }         }     } catch (Exception e) {     }     return null; } 

Then you can implement findByRole using the serialize method

public static List<User> findByRole(Role role) {     return find.where().eq("role", serialize(role)).findList(); } 


回答2:

Looks like the issue is that you have a roles list, not a single property on your user.

@Constraints.Required @ManyToMany public List<Role> roles = new ArrayList<Role>(); 

To query against that list, try:

public static List<User> findByRole(Role role) {     return find.where().in("roles", role).findList(); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!