系列文章之2:netbeans对jpa的支持
内容要点:1 实体向导的逆向正向支持 2 JPA控制器类的生成 以及定制spring下的服务类的模板
概括起来2点:
1 反向支持
2 正向支持
详细:
1 反向支持,即逆向工程
当设计好数据库以后,就可以选择面板里的从数据库里生成实体类了。
netbeans对mysql的支持非常好,生成的代码基本一个字不用改就能用了。sql server的只需改一个地方,就是添加主键的生成方式。就是复制一句 @GeneratedValue(strategy = GenerationType.AUTO)
不知是否是故意的,不过这样确实促进使用mysql。
缺点:可控制性不是很好,主要是字段名字可能不是自己期望的。当然了,自己随便改,因为生成的实体类里有字段的映射属性。也就是说,如果想复合自己的意愿,还是需要改动代码的。除非建立数据库时,字段名字就考虑使用规范好的。
2 正向支持
通过面板,创建实体类。 推荐这种做法,尤其学习的话,使用这个,能锻炼OO的编程能力。然后让框架自动创建数据库表。
2.1 通过向导 -----创建实体类
输入名称如 SaleOrder ,将生成如下代码,剩下就是自己添加多余的属性了。
@Entity
public class SaleOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof SaleOrder)) {
return false;
}
SaleOrder other = (SaleOrder) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.test.SaleOrder[id=" + id + "]";
}
}
比如添加订单总价:
private BigDecimal totalPrice;
注意:这里无需加注释,默认的就是@Column。可以充分利用默许方式。
完整的代码可以参考如下: 其他属性可以自己添加
@Entity
public class SaleOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private BigDecimal totalPrice;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof SaleOrder)) {
return false;
}
SaleOrder other = (SaleOrder) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.test.SaleOrder[id=" + id + "]";
}
}
2.2 创建订单明细它与上面的订单是多对一关系
面板--创建实体类代码如下:
@Entity
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof OrderItem)) {
return false;
}
OrderItem other = (OrderItem) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.test.OrderItem[id=" + id + "]";
}
}
建立他们间的关联:
在上面的类文件里输入
private SaleOrder saleOrder;
看截图:
左边有个黄色叹号,点击,提示生成实体映射关系:看截图:
选择创建双向ManyToOne关系,弹出设置属性,即SaleOrder 里用来与many对应的字段的名称,输入名称即会生成代码。
生成后的代码这里省略了。
最后总结2点:
1 一般的字段不需要加上注释,比如@Column除非是string的字段限制长度,默认是255,如果对性能要求不苛刻,那就万事都可省呀。
2 netbeans自动创建实体间映射。
2.3 生成实体控制器
面板————生成实体控制器类
添加要生成的实体:这里演示,我只添加SaleOrder,生成代码如下:
public class SaleOrderJpaController {
public SaleOrderJpaController() {
emf = Persistence.createEntityManagerFactory("testtempletePU");
}
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(SaleOrder saleOrder) {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
em.persist(saleOrder);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public void edit(SaleOrder saleOrder) throws NonexistentEntityException, Exception {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
saleOrder = em.merge(saleOrder);
em.getTransaction().commit();
} catch (Exception ex) {
String msg = ex.getLocalizedMessage();
if (msg == null || msg.length() == 0) {
Integer id = saleOrder.getId();
if (findSaleOrder(id) == null) {
throw new NonexistentEntityException("The saleOrder with id " + id + " no longer exists.");
}
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}
public void destroy(Integer id) throws NonexistentEntityException {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
SaleOrder saleOrder;
try {
saleOrder = em.getReference(SaleOrder.class, id);
saleOrder.getId();
} catch (EntityNotFoundException enfe) {
throw new NonexistentEntityException("The saleOrder with id " + id + " no longer exists.", enfe);
}
em.remove(saleOrder);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public List<SaleOrder> findSaleOrderEntities() {
return findSaleOrderEntities(true, -1, -1);
}
public List<SaleOrder> findSaleOrderEntities(int maxResults, int firstResult) {
return findSaleOrderEntities(false, maxResults, firstResult);
}
private List<SaleOrder> findSaleOrderEntities(boolean all, int maxResults, int firstResult) {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select object(o) from SaleOrder as o");
if (!all) {
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
}
return q.getResultList();
} finally {
em.close();
}
}
public SaleOrder findSaleOrder(Integer id) {
EntityManager em = getEntityManager();
try {
return em.find(SaleOrder.class, id);
} finally {
em.close();
}
}
public int getSaleOrderCount() {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select count(o) from SaleOrder as o");
return ((Long) q.getSingleResult()).intValue();
} finally {
em.close();
}
}
}
可见,这代码适合单独使用JPA的环境。上面的方法名称不合意的话,可以动手修改模板。
工具---模板 找到持久性
选中 其下面的 基于实体类的JPA控制器, 这个它已经有的是不让你改的,选中它,在右边点复制,然后下面就会出来一个。重命名为 我的JPA控制器类:
然后,在编辑器中打开。发现是空白,持久性模块里的模板的扩展性做的不好,spring模块就可以自己编辑。
这里就当介绍一个方法吧,如何定制自己的模板,以便快速开发。
至于本文的这个问题,我想通过添加新插件来解决,当我做完善了,我再发文章。不过生成spring下的JPA服务类其实放在这里不如放在spring模块里,可能因此,netbeans开发组没给太多java持久性扩展模板支持。
下面我们打开spring的模板:
选中抽象控制器,然后复制,下面就出个新的,然后改名为JPA服务类,然后在编辑器中编辑。
小提示:看能不能扩展,看下原来那个能不能在编辑器中打开就知道了。,上面的Java持久性里的服务类是不能在编辑器中打开的。
我们照着改下:
package ${package};
</#if>
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author ${user}
*/
@Service
@Transactional
public class ${name}ServiceBean extends DaoSupport<${name}> implements ${name}Service{
}
看到上面的DaoSupport以及实现的接口,我们的${name}就是向导里输入的名字,这里我们直接复制实体类名就可以了。DaoSupport是一个基础类,封装了每个实体类都具备的 添加 更新 删除 查询出List的功能。可以把这个类自己取个名字,打成jar包,固定下来,至于如何命名,那是自己的事情,但是千万别和人家的类库冲突了。
比如 打包成到 self.spring.service.base。 self代表自己的jar包。
在上述模板里加上:
self.spring.service.base.DaoSupport,
另外上面引入了注释
那么通过模板生成实体服务类时,就省去了这部分劳动了。是不是就等于提高效率了。
比如键入SaleOrder那么将生成如下代码:
package com.test.service;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class SaleOrderServiceBean extends DaoSupport<SaleOrder> implements SaleOrderService{
}
好了,先到这里,不过有个问题,服务类不能和实体类放一起,否则输入名字时和实体类名相同,不能创建,因为服务类一般放在service这样命名的包中,因此,应该不用考虑这个问题。
上面的DaoSupport我还没打包,没添加到模板中。至于想生成方法,自己定制就可以了,总之,自己看着弄,适合自己就是最好的。
now!开始定制自己的IDE吧。由于我的水平有限,高级定制需要很长时间去学习与研究,不是短时间能具备的。但是通过定制已有模板,是最简单的提供效率的方法,它几乎不需要任何编程支持,仅仅改下模板就可以了。
如果有相关的文章,可以提供给我,万分感谢!共同进步。谢谢观看。。