Blog of Samperson

J2EE第6次作业的坑 (JPA技术)

2018-01-08

首先对薛老师表示感谢!第6次作业总体来说没什么难度,只是PPT上给的xml文件有坑。当然我这边的两张数据库表是完全独立的,所以从第5次作业过渡到第6次会容易一些。更多的语法和内容可以参考PPT,有什么大家都碰到的坑我还是会不断继续整理在这篇博客里的。

项目要求

整体要求

[1] 客户登录, 跟据客户的ID/PW, 查询订单情况, 并根据具体情况, 返回不同结果:有缺货的订单项,警示页面;正常结果: 标准页面, 每一项订单包括多项属性(时间、名称、数量、价格), 分页显示;未知的客户ID: 错误页面
[2] 使用过滤器解决表单中的中文请求后的乱码问题
[3] 统计在线人数:总人数、已登录人数、游客人数
[4] 用户通过URL直接访问XXXServlet或XXX.JSP时,已登录用户可访问,未登录用户转向登录页面

第6次作业要求

[1] 基于第5次作业
[2] 数据访问层设计使用 JPA EntityManager
[3] Model的设计使用 Entity Beans

配置文件

[1] 首先下载 javax.persistence_2.0.0.jar,并添加到项目依赖中。
[2] PPT上面给的 persistence.xml 有坑,正确的配置文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<!--必须要有name属性,不能为空 -->
<persistence-unit name="nju">
<!--厂商的特定属性 -->
<jta-data-source>java:jboss/datasources/mysqlDS</jta-data-source>

<class>model.User</class>
<class>model.Order</class>

<properties>
<!--配置Hibernate方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<!--自动输出schema创建DDL语句 -->
<property name="hibernate.hbm2ddl.auto" value="none"/>

<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
</properties>
</persistence-unit>

</persistence>

注意 <property name=“hibernate.transaction.jta.platform” value=“org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform”/> </properties> 非常重要。
另外 <class> 标签里需要根据自己的项目进行修改。

[3] 配置文件放在 src/META-INF 下面,没有这个文件夹需要自己创建。如果是 maven 项目,则应该放在 resources 文件夹里。(因为我自己写作业时不是 maven 项目,所以上一篇博客忘记说明了,导致一些同学出现了问题。在我内疚的时候,薛老师指出这应该是基本常识,但还是觉得应该说明一下)

Model设计

model的修改必须与数据库表对应好,包括每一个column的名字,不然服务器端会报错。以user为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "users")
public class User implements Serializable {

@Id
@Column(name = "user_id")
private int userId;

@Column(name = "password")
private String password;

... // Constructor, Getter and Setter
}

DaoImpl设计

Container-Managed EntityManagers 和 Application-Managed EntityManagers

1
2
3
4
5
6
7
8
9
10
@PersistenceUnit(name = "nju")
private EntityManagerFactory factory;

@PersistenceContext
private EntityManager em;

public UserDaoBean() {
factory = Persistence.createEntityManagerFactory("nju");
em = factory.createEntityManager();
}

这边没有什么难度,注意 persistence-unit 的 name 和配置文件对应就好。

一些常用查询语句的注意事项

[1] find:需要注意类型转换,例如:

1
User user = em.find(User.class, Integer.valueOf(userId));

[2] createQuery:通过使用泛型来减少强制类型转换,例如:

1
2
3
4
5
6
TypedQuery<Order> query = em.createQuery("FROM model.Order o WHERE o.userId = userId", Order.class);
List<Order> list = query.getResultList();

em.clear();
// 在处理大量实体的时候,如果不把已经处理过的实体从EntityManager中分离出来,将会消耗大量的内存
// 此方法分离内存中受管理的实体Bean,让VM进行垃圾回收

另外还要注意 FROM 后面跟的是model的路径名字,不是数据库表的名字。

[3] createNativeQuery:使用原生语句,例如下面的语句使用了 mysql 的 LIMIT 语法,起到数据库分页的作用:

1
2
Query query = em.createNativeQuery("SELECT * FROM user_orders WHERE user_id = "
+ id + " LIMIT " + start + ", " + pageSize, Order.class);

J2EE的小作业还有3次,分别是 Hibernate、 Spring 和 Struts,按照老师的进度预计应该本周会布置第7次作业,下周三布置第8次和第9次,所以在时间上还是蛮有挑战性的。写博客是希望大家可以更好的一起讨论和交流,在上一篇博客发布后收到了很多同学们的私信和评论,有的针对某些问题进行探讨,有的找我帮忙debug(我也竭尽全力帮助大家),还有一些感激和鼓舞。在这里想谢谢大家!让我们一起营造更好的学习氛围,一起学习、一起进步!