Ebean findPagedList() throw Exception的分析处理过程
来源:互联网 发布:变频器仿真软件 编辑:程序博客网 时间:2024/05/18 20:08
Ebean findPagedList() throw Exception的分析处理过程
一、定义User
import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name = "t_user")public class User { @Id private String id; @Column private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; }}
二、执行测试
@Test public void testFindPageList() { Query<User> find = Ebean.find(User.class); find.setMaxRows(1); find.setFirstRow(1); System.out.println(find.findPagedList().getList()); }抛出Exception:Caused by: java.lang.IllegalStateException: Bean class User is not enhanced?
三、分析过程
step1
进入BeanDescriptorManager.java:1442查看错误处,看到抛出Exception这里有个hasEntityBeanInterface的校验:
进入到hasEntityBeanInterface方法,源码如下:
private boolean hasEntityBeanInterface(Class<?> beanClass) { Class<?>[] interfaces = beanClass.getInterfaces(); Class[] var3 = interfaces; int var4 = interfaces.length; for(int var5 = 0; var5 < var4; ++var5) { Class<?> anInterface = var3[var5]; if (anInterface.equals(EntityBean.class)) { return true; } } return false;}由此可知,Entity Bean必须实现一个EntityBean的接口(在网上看到的都没有实现这个接口和集成Model的,不知道是版本问题还是用的方式不对)step2
User实现EntityBean接口:
import io.ebean.bean.EntityBean;import io.ebean.bean.EntityBeanIntercept;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;import java.beans.PropertyChangeListener;@Entity@Table(name = "t_user")public class User implements EntityBean { @Id private String id; @Column private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String[] _ebean_getPropertyNames() { return new String[0]; } public String _ebean_getPropertyName(int i) { return null; } public String _ebean_getMarker() { return null; } public Object _ebean_newInstance() { return null; } public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) { } public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) { } public void _ebean_setEmbeddedLoaded() { } public boolean _ebean_isEmbeddedNewOrDirty() { return false; } public EntityBeanIntercept _ebean_getIntercept() { return null; } public EntityBeanIntercept _ebean_intercept() { return null; } public void _ebean_setField(int i, Object o) { } public void _ebean_setFieldIntercept(int i, Object o) { } public Object _ebean_getField(int i) { return null; } public Object _ebean_getFieldIntercept(int i) { return null; }}执行测试,抛出Exception:
进入BeanPropertiesReader.java:43查看错误处,看到getProperties源码如下:
private String[] getProperties(Class<?> clazz) { try { Field field = clazz.getField("_ebean_props"); return (String[])((String[])field.get((Object)null)); } catch (Exception var3) { throw new IllegalStateException("Error getting _ebean_props field on type " + clazz, var3); }}这里获取一个public static的_ebean_props字段,因为这个字段存储的是当前实体类(User)对应数据库的字段,所以用field.get((Object)null)来限制该字段必须是public static字段。
step3
增加_ebean_props字段后,再次执行测试,抛出Exception:
进入到BeanDescriptor.java:523查看错误处,看到如下代码(这里的_ebean_getIntercept()就是User实现的EntityBean的_ebean_getIntercept()):
EntityBeanIntercept ebi = this.prototypeEntityBean._ebean_getIntercept(); this.idPropertyIndex = this.idProperty == null ? -1 : ebi.findProperty(this.idProperty.getName());
step4
重写User中的_ebean_getIntercept():public EntityBeanIntercept _ebean_getIntercept() { return new EntityBeanIntercept(this); }执行测试,发现结果字段值均为null:
step5Debugger跟踪源码运行,发现设置属性值的方法在EnhanceBeanPropertyAccess.Setter.set(...)方法中会调用实体类的_ebean_setField(...)方法对属性进行赋值操作(即赋值操作由EntityBean._ebean_setField(...)方法完成)。
重写User的_ebean_setField方法:
public void _ebean_setField(int i, Object o) { try { Field field = this.getClass().getDeclaredField(get_ebean_props()[i]); field.setAccessible(true); field.set(this, o); } catch (Exception e) { e.printStackTrace(); }}执行测试,运行结果如下:
四、整理后的代码
定义AbstractEntityBean,实现EntityBean接口:
import io.ebean.bean.EntityBean;import io.ebean.bean.EntityBeanIntercept;import java.beans.PropertyChangeListener;import java.lang.reflect.Field;public abstract class AbstractEntityBean implements EntityBean { // 因为每个实体类都需要一个静态的_ebean_props属性,所以这里定义一个方法获取这个静态属性方便下面的代码调用 public abstract String[] get_ebean_props(); public String[] _ebean_getPropertyNames() { return get_ebean_props(); } public String _ebean_getPropertyName(int i) { return null; } public String _ebean_getMarker() { return null; } public abstract Object _ebean_newInstance(); public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) { } public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) { } public void _ebean_setEmbeddedLoaded() { } public boolean _ebean_isEmbeddedNewOrDirty() { return false; } public EntityBeanIntercept _ebean_getIntercept() { return new EntityBeanIntercept(this); } public EntityBeanIntercept _ebean_intercept() { return null; } public void _ebean_setField(int i, Object o) { try { Field field = this.getClass().getDeclaredField(get_ebean_props()[i]); field.setAccessible(true); field.set(this, o); } catch (Exception e) { e.printStackTrace(); } } public void _ebean_setFieldIntercept(int i, Object o) { } public Object _ebean_getField(int i) { return null; } public Object _ebean_getFieldIntercept(int i) { return null; }}修改User,继承AbstractEntityBean,实现EntityBean接口(因为Class.getInterfaces()只能获取到当前类实现的接口,所以这里再实现一次):
import io.ebean.bean.EntityBean;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name = "t_user")public class User extends AbstractEntityBean implements EntityBean { public static String[] _ebean_props = new String[] {"id", "username"}; @Id @Column(name = "id") private String id; @Column private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String[] get_ebean_props() { return _ebean_props; } @Override public Object _ebean_newInstance() { return new User(); } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", username='" + username + '\'' + '}'; }}测试代码TestDBConnection
import io.ebean.Ebean;import io.ebean.Query;import org.junit.Test;public class TestDBConnection { @Test public void test() { System.out.println("cnt : " + Ebean .createSqlQuery("select count(0) as cnt from t_user").findOne() .getInteger("cnt")); } @Test public void testFindPageList() { Query<User> find = Ebean.find(User.class); find.setMaxRows(1); find.setFirstRow(1); System.out.println(find.findPagedList().getList()); }}
五、总结
这种不与其他框架集成的方式:
- 实体类需要实现EntityBean接口
- 实体类需要有一个public static的_ebean_props字段存储查询的字段名
- 实体类中的_ebean_getIntercept()返回值不能为null(即不能是空实现)
- 查询数据后Ebean会调用_ebean_setField方法为属性赋值,实体类中的_ebean_setField方法不能是空实现
- Ebean findPagedList() throw Exception的分析处理过程
- php throw new Exception php异常处理
- Exception和RuntimeException,throws和throw分析
- throw Exception
- 能用if- else/throw-exception进行错误/异常处理的地方就不要用assert。
- throw new Exception抛出异常的接收
- throw Exception 的执行效率试验
- 对 Exception 的catch,throw,throws
- Java exception throws && throw 的区别
- throw exception和 try catch的区别
- Java中"throw new Exception() "和"new Exception()"的区别
- ebean的学习
- Java异常处理( try catch finally throw throws exception error)
- php中的error与exception的区别与处理过程
- C++ unexpected throw exception
- throw an exception
- throw new Exception
- throw new Exception
- tar.gz包解压失败
- 【AI_数学知识】数学分析
- JVM虚拟机参数总结分享
- Linux下mysql简单配置
- python面向对象的补充(一个对象调用另一个对象)
- Ebean findPagedList() throw Exception的分析处理过程
- VxWorks任务状态的转换
- Hibernate的HQL使用Oracle的Regexp_like函数的方式
- mysql 双机热备
- Laravel migrate时报错: Syntax error or access violation: 1071 Specified key was too long
- 关于nginx重新编译
- PHP基礎_星期
- Jzoj5458【NOIP2017提高A组冲刺11.7】质数
- ubuntu16.04 安装tensorflow1.4