Querying @ElementCollections

在JPA 2.0中使用到注解 @ElementCollection

public class Budget extends IdEntity {

@ElementCollection(fetch = FetchType.EAGER)
@Column(name = "projectLeaderIDs")
private List<String> projectLeaderIDs;
}

在@ElementCollection的属性中做查询

String sql = "select count(b) from " + Budget.class.getSimpleName()
                + " b,IN (b.projectLeaderIDs) s where :userID in s";

show sql:

Hibernate: 
    select
        count(budget0_.id) as col_0_0_ 
    from
        budget budget0_ 
    inner join
        Budget_projectLeaderIDs projectlea1_ 
            on budget0_.id=projectlea1_.Budget_id 
    where
        ? in (
            projectlea1_.projectLeaderIDs
        ) limit ?

cannot simultaneously fetch multiple bags 问题的解决办法

完整的异常信息如下:

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
	at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:94)
	at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:119)
	at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:71)
	at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:54)
	at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:133)
	at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1914)
	at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1937)
	at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3205)
	at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3191)
	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:348)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872)
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906)
	at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)

问题是什么时候出现的呢?

当一个实体对象中包含多于一个non-lazy获取策略时,比如@OneToMany,@ManyToMany或者@ElementCollection时,获取策略为(fetch = FetchType.EAGER)

继续阅读cannot simultaneously fetch multiple bags 问题的解决办法

[10/01周主题] – Web 项目开发中的常见问题

这周来一直在赶一个Web项目,没多少时间focus到其他上面,于是这周的主题就干脆做个整理,整理下web项目开发时遇到的一些问题和解决办法。

本周主题:Web 项目开发中的常见问题

一、中文乱码

建议统一使用UTF8,或者全局做个filter处理。

二、表单校验

使用第三方校验框架, 而非自己去写,可以减少很多工作量。

三、Ajax的使用

首页尽量少用ajax,页面初次加载时常会加载不上来,尤其多个Ajax实例同时运行。

四、UI 规范

UI最好是出Demo,跟客户确认,定终稿,然后开发按最终效果图实现页面最好,否则没有页面或者效果图,即使有统一的规范,还是会浪费很多时间去调UI问题。

五、浏览器的兼容问题

虽然IE6基本上淘汰了,可老机器上使用IE6的还是不少的,Css 在处理兼容问题时,建议分开处理,在页面进行浏览器version判断,读取不同的css,这样管理和调整起来都方便。

六、比较完整的测试数据

页面框架搭完了,看着效果不错,可是填完数据后会发现和想象的不太一样。

七、用JPA Or JDBC 与数据库交互

JPA与JDBC相比之下,使用JPA大大减少了编程人员的工作量,因此还是偏向使用JPA,特殊环境下再选择JDBC

[09/48周主题] – JPA

是本博客开始周主题的第一个主题,周主题计划按自然周为标记,记录一年内每周的关注主题,这样至少可以提醒自己哪个周的没有写了。

本期主题:JPA

对于JPA不熟悉的朋友可以先看看这里:百度百科之JPA 里面介绍了JPA的起源,优势,厂商等。

本文是由网上其他网友的经验和自己的经验总结而成,个人能力有限,不免有错误之处,如有误导之地恳请指正。欢迎大家提出宝贵意见,以便完善。
context

一、JPA中必须知道的4个状态

1. 新建态(New):新创建的实例对象,没有持久化主键。

简单讲就是你刚new出来的对象,谁也管不着的。

2. 受控态(Managed):在持久化上下文中受管理的对象;

先理解两个概念持久化主键持久化上下文:持久化上下文是由与该上下文相关联的 EntityManager 实例管理的一组实体实例,关键词是EntityManager, 新创建的实体尚未被托管于持久化上下文中,EntityManager无法对它进行管理。EntityManager对持久化上下文中的实体进行管理,必然通过主键去查找实体对象,这个主键就是持久化主键。

3. 游离态(Detached):游离于持久化上下文之外的实例对象;

4. 删除态(Removed):被删除的实例对象。

这些状态通过调用EntityManager的接口方法进行相互迁移

二、EntityManager 的常用API

void persist(Object entity)

  • 通过persist()方法,新建状态将转换为受控状态。这意谓着当persist ()方法所在的事务提交时,实体的数据将保存到数据库中。
  • 如果实体已经被持久化,那么再调用persist()操作,会抛出异常 Duplicate entry。
  • 如果对一个已经删除的实体调用persist()操作,删除态的实体又转变为受控态,实体的数据将保存到数据库中。
  • 如果persist的是一个游离实体(即上下文中没有它),而上下文中又没有它的受管版本,数据库却有这个实体,那么会抛出异常 Duplicate entry;
  • 如果persist的是一个游离实体(即上下文中没有它),而上下文中却有它的受管版本,数据库中也有了这个实体,那么EntityManager在persist它的时候就会抛出异常:javax.persistence.EntityExistsException
  • 在一个实体上调用persist()操作,将广播到和实体关联的其他实体上,执行相应的级联持久化操作;

void remove(Object entity)

  • 通过remove()方法删除一个受控的实体;
  • 如果实体声明为级联删除(cascade=REMOVE 或者cascade=ALL ),被关联的实体也会被删除;
  • 在一个新建状态的实体上调用remove()操作,将被忽略;
  • 如果在游离实体上调用remove()操作,将抛出 IllegalArgumentException,相关的事务将回滚;
  • 如果在已经删除的实体上执行remove()操作,也会被忽略

T merge(T entity)

  • 将一个游离态的实体持久化到数据库中,并转换为受控态的实体;
  • Merge一个游离版本,同时上下文中却有它的受管版本,那么返回的是受管版本,数据库中的数据更新

Query createQuery(String qlString)

  • 根据JPA的查询语句创建一个查询对象Query

T find(Class entityClass, Object primaryKey)

  • 以主键查询实体对象,entityClass是实体的类,primaryKey是主键值

三、使用时应注意的一些情况

1. EntityManager对象的事务管理方式有两种,分别为JTA和RESOURCE_LOCAL,即Java Transaction API方法和本地的事务管理。JPA中的事务类型通过persistence.xml文件中的“transaction-type”元素配置。JTA事务只能运行在J2EE的环境中,即EJB容器中和Web容器中;而在J2SE环境中只能使用RESOURCE_LOCAL管理事务。

2. 注意OneToMany,ManyToOne,ManyToMany三种关系时的参数配置.

3. Merge也有Persist的功能,数据库中有就merge,没有添加。

4. 注意Transaction的使用,不要一个方法中有几个Transaction。

5. 正确使用Eager和Lazy能显著提交效率。

6. 使用persist,只需注意操作的对象要么是new,要么是受管的,否则肯定出问题。

7. 使用merge,基本上无论如何都不会抛异常,但后续的操作必须针对该方法返回的新受管对象进行操作,否则肯定出问题。

四、参考资料

1. http://www.oracle.com/technology/products/ias/toplink/jpa/index.html

2. http://baike.baidu.com/view/1036852.htm?fr=ala0

3. http://java.sun.com/javaee/technologies/persistence.jsp

4. http://pz0513.blog.51cto.com/443986/113098

==本文谢绝转载,谢谢==

周主题

周开始实施“周主题”计划,就是每周都有一个关注的主题内容,了解,掌握,到熟知,可以是各方面的内容,

自己感兴趣的,好玩的等,不过应该会以技术应用居多,毕竟目前还属于技术型,有些内容一周不行可以两周,

甚至三周…。

推出此计划的目的是自己太懒惰了,习惯性的东西太多,长期计划执行没有持久性,这才决定推出短期的以周为

单位的任务计划,以鞭策自己,你需要快点涉猎各方面的东西,而且是持久的。

预告下本周的主题:JPA, 主要结合项目中的使用,比较系统的了解JPA的应用情况。