假如一个餐厅中有一个客人A 请了 一大群朋友来吃饭,
开了三张桌子,创建三张订单,就是订单三张表table (父),明细表为:菜单table(子);
炒出来的菜分别往不同的 餐桌上送。
忽然有些朋友有事情要走了,一个订单废弃,炒的菜取消,这个称为:数据孤儿
ssh框架,跟以往一样,分四个包:
action :控制层,service:业务逻辑处理层;
dao :数据库连接层;entity :实体类
不同以往,有2个实体类,一个子,一个父。
改变:我们将不再写mysql,让实体类注入,自动写mysql;
lib目录的 ssh框架 的jar包,请到我之前发的 百度云 下载 或者自行配置。
index.jsp: 主页只有一个 index 用来测试 是否成功。无关紧要。
web.xml 的配置没有变。
代码如下:
order.entity 实体类 Order.java (主表,父表)
@OneToMany(mappedBy="order",cascade={CascadeType.ALL},fetch=FetchType.EAGER)
这个注解联系2个实体类
package order.entity;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity //实体类注解
@Table(name = "t_order") //告知调用者,sql的表名
public class Order {
private Integer id;// 主键
private Integer pCount;// 人数
private Date pubDate;//日期
private Set<OrderItem> orderItems = new HashSet<OrderItem>();
@OneToMany(mappedBy="order",cascade={CascadeType.ALL},fetch=FetchType.EAGER)
public Set<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="p_Count",nullable=false)
public Integer getpCount() {
return pCount;
}
public void setpCount(Integer pCount) {
this.pCount = pCount;
}
@Column(name="pub_Date",nullable=false)
public Date getPubDate() {
return pubDate;
}
public void setPubDate(Date pubDate) {
this.pubDate = pubDate;
}
}
OrderItem.java 第二个实体类(从表,点菜表,子表)
@ManyToOne(cascade={CascadeType.ALL},optional=true,fetch=FetchType.EAGER)
这个注解让2个表联系起来。
package order.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "t_order_item")
public class OrderItem {
private Integer id;//主键
private String detailDesc;//明细描述
private Integer price;//单价
private Integer cCount;//数量
//错误演示
//private Integer order_id;
private Order order;
@ManyToOne(cascade={CascadeType.ALL},optional=true,fetch=FetchType.EAGER)
@JoinColumn(name="orderid")
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="detail_desc",nullable=false,length=50)
public String getDetailDesc() {
return detailDesc;
}
public void setDetailDesc(String detailDesc) {
this.detailDesc = detailDesc;
}
@Column(name="price",nullable=false)
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Column(name="c_count",nullable=false)
public Integer getcCount() {
return cCount;
}
public void setcCount(Integer cCount) {
this.cCount = cCount;
}
}
order.action 层:OraerAction.java
我们只有一个显示的方法,哈哈。
<span style="font-size:18px;">package order.action;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport;
import order.service.OrderService;
@SuppressWarnings("serial") //取消类警告的注解
@Controller //控制层的注解
@Scope("prototype") //非单例注解
public class OrderAction extends ActionSupport {
@Autowired
private OrderService orderService;
public String getAllOrder(){
orderService.getAllOrder();
return "ok1";
}
}</span>
order.service层 OrderService.java 接口
<span style="font-size:18px;">package order.service;
import java.util.List;
import order.entity.Order;
public interface OrderService {
public List<Order> getAllOrder();
}</span>
order.service层 OrderServiceImpl.java 接口
<span style="font-size:18px;">package order.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import order.dao.OrderDao;
import order.entity.Order;
@Transactional
@Service
@Scope("prototype")
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Override
public List<Order> getAllOrder() {
return orderDao.getAllOrder();
}
}</span>
orderdao层 OrderDao 接口
<span style="font-size:18px;">package order.dao;
import java.util.List;
import order.entity.Order;
public interface OrderDao {
public List<Order> getAllOrder();
}</span>
orderdao层 OrderDaoImpl ;
我们在 daoImpl,直接往mysql 建database,建table ,插入数据信息!
package order.dao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import order.entity.Order;
import order.entity.OrderItem;
@Repository //数据库访问层注解
@Scope("prototype") //非单例注解
public class OrderDaoImpl implements OrderDao {
@Autowired
private SessionFactory sessionFactory;
//删除主表( 删除儿子 )
public List<Order> getAllOrder() {
Session session = sessionFactory.getCurrentSession();
Order order1 = session.get(Order.class,1);
session.delete(order1);
return new ArrayList<Order>();
}
//删除从表(删除儿子)
public List<Order> getAllOrder4() {
Session session = sessionFactory.getCurrentSession();
OrderItem o1 = session.get(OrderItem.class,2);
//解除父子关系(1.先老爸不认儿子,2.儿子也不认老爸),从此小孩变成一个孤儿
o1.getOrder().getOrderItems().remove(o1);
o1.setOrder(null);
session.delete(o1);
return new ArrayList<Order>();
}
//从 明细表(从表)反过来获取主表信息
public List<Order> getAllOrder3() {
Session session = sessionFactory.getCurrentSession();
OrderItem o1 = session.get(OrderItem.class,2);
System.out.println("从表信息--描述:"+ o1.getDetailDesc());
Order order1 = o1.getOrder();
System.out.println("主表信息--日期:"+ order1.getPubDate());
return new ArrayList<Order>();
}
//测试从主表获得从表信息
public List<Order> getAllOrder2() {
Session session = sessionFactory.getCurrentSession();
//搜索出1条order对象(1个对象),生成出一个left outer join sql语句,返回2条记录,
//并且hibernate自动把这2条记录,封装到order对象中的orderItems这个set对象里面存放
Order order1 = session.get(Order.class,1);
System.out.println("主表信息--日期:"+order1.getPubDate());
Set<OrderItem> orderItems = order1.getOrderItems();
for (OrderItem item : orderItems) {
System.out.println(" 从表信息--描述:"+ item.getDetailDesc());
}
return new ArrayList<Order>();
}
//测试添加数据
public List<Order> getAllOrder1() {
Session session = sessionFactory.getCurrentSession();
//订单
Order order1 = new Order();
order1.setpCount(4);
order1.setPubDate(new Date());
//明细中菜1
OrderItem o1 = new OrderItem();
o1.setcCount(15);
o1.setPrice(13);
o1.setDetailDesc("炒菜心");
//明细中菜2
OrderItem o2 = new OrderItem();
o2.setcCount(15);
o2.setPrice(13);
o2.setDetailDesc("麻婆豆腐");
//配置关系
order1.getOrderItems().add(o1);
order1.getOrderItems().add(o2);
o1.setOrder(order1);
o2.setOrder(order1);
//保存
session.save(order1);
//session.save(o1);
//session.save(o2);
return new ArrayList<Order>();
}
}
要注意:菜单(从表,子表)可以增减,但是餐桌(主表,父类)可不能随便增减!
applicationContext.xml 这个作用巨大哦!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!-- 原理:自动注入processor解析器,用来解析注解 -->
<!-- <context:annotation-config/> -->
<!-- 自动扫描包,也会自动注入解释器,所以不需要 context:annotation-config -->
<context:component-scan base-package="order"></context:component-scan>
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入连接池,包含了数据库用户名,密码等等信息 -->
<property name="dataSource" ref="myDataSource" />
<!-- 配置Hibernate的其他的属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.autocommit">false</prop>
<!-- 开机自动生成表 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="mappingResources">
<list>
</list>
</property>
<property name="packagesToScan">
<list>
<value>order.*</value>
</list>
</property>
</bean>
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<!-- 每300秒检查所有连接池中的空闲连接 -->
<property name="idleConnectionTestPeriod" value="300"></property>
<!-- 最大空闲时间,900秒内未使用则连接被丢弃。若为0则永不丢弃 -->
<property name="maxIdleTime" value="900"></property>
<!-- 最大连接数 -->
<property name="maxPoolSize" value="2"></property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
jdbc.properties 这个是文本的形态(txt)
用来给不懂代码的人配置不同的sql的,这里还是2套数据库:mysql , oracle
数据库名:news ,表2个:t_order;t_order_item
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/news
jdbc.user=root
jdbc.password=
#oracle
jdbc_oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc_oracle.url=jdbc:oracle:thin@127.0.0.1:1521:orcl
jdbc_oracle.user=news
jdbc_oracle.password=
struts.xml 这里有着所有的方法
这里只有:显示成功,删除成功2个
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.objectFactory" value="spring" />
<!-- 第1步:先定义一个包 -->
<package name="mypck001" extends="struts-default">
<action name="OrderAction_*" class="orderAction" method="{1}">
<result name="ok1">/WEB-INF/jsp/index.jsp</result>
<!-- 希望删除成功后,重新执行1次首页显示内容 -->
<result name="deleteOK" type="redirectAction">NewsAction_showAllNews.action?message=deleteok&id=${id}</result>
</action>
</package>
</struts>
web.xml 每次都一样:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>news</display-name>
<welcome-file-list>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.sendRedirect("OrderAction_getAllOrder.action");
%>
启动mysql
查询一下,发现mysql已经有了信息
而且 2个表示连接起来的。
说明我们已经完成 多表并联了。