读书笔记

来源:互联网 发布:磨砂玻璃 隐私 知乎 编辑:程序博客网 时间:2024/05/05 12:25

A#hashCode()方法如下实现:
public class A{
    private Integer id;
    ...
    public int hashCode(){
        return id.hashCode() * 11;
    }
}
这样写是有问题的:当没给id赋过值时,id = null,这样就会报NullPointerException,所以这里需要这样写:
public int hashCode()
{
    return (id == null ? 0 : id.hashCode()) * 11;
}

但建议程序中尽量使用基本数据类型,而不是封装类型:

public class B{
    private int id;
    ...
    public int hashCode(){
        return Integer.valueOf(id).hashCode() * 11;
    }
}

 

cascade:指定哪些操作会由主表记录级联到从表记录。所以要想弄清楚谁更新后会级联更新谁,就要弄清楚谁是主表、谁是从表:当A表外间引用B表时,A表为从表,B表为主表。

 

HQL语句中关键字、函数不区分大小写,但包名、类名、属性名区分大小写。

 

事务具体4个特性:原子性、一致性、隔离性和持续性,简称CRUD。
原子性:事务是应用中不可再分的最小逻辑执行体;
一致性:事务执行的结果,必须使数据库从一个一致性状态变成另一个一致性状态;
隔离性:各个事务的执行互不干扰,比如当前事务不能看到另一个事务未提交的数据;
持久性:指事务提交后必须被持久化。

 

Hibernate自身并不提供事务控制行为,它直接使用底层JDBC连接、JTA资源或其它资源的事务。

 

创建Session时并不会立即打开与数据库之间的连接,只有进行了数据库操作后才会获取数据库连接。

 

应用保存、修改、删除持久化实体时,Session并不立即刷新数据库,而是缓存在当前Session一级缓存中,直到程序显式调用Session.flush()方法或关闭Session才会刷新数据库。

 

Java EE应用的传统事务有两种策略:全局事务和局部事务。
全局事务:全局事务由应用服务器管理,需要底层服务器的JTA支持。全局事务可跨越多个事务性的资源,保证在多个事务性资源间跨越时资源的一致性。
局部事务:局部事务和底层采用的持久化技术相关:采用JDBC持久化技术时,需要使用Connection对象操作事务;采用Hibernate持久化技术时,需要使用Session对象操作事务。使用局部事务,应用服务器不需要参与事务管理,因此不能保证跨越多个事务性资源的事务的正确性。
 
PlatformTransactionManager接口是Spring事务策略的核心,它有三个方法:getTransaction()、commit()和rollback(),它是一个与平台无关的事务接口,底层采用不同的持久化技术则需要使用不同的实现类,通过注入相关的平台特性还可以在全局事务与局部事务之间切换。可见Spring的事务策略是非常灵活的。

 

声明式地创建Spring容器的配置为:
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
     classpath:spring.xml
    </param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
为什么这样配置就可以在系统启动时创建Spring容器?
我们先关注ServletContextListener接口的源码:
public interface javax.servlet.ServletContextListener extends java.util.EventListener {
    public abstract void contextInitialized(javax.servlet.ServletContextEvent arg0);
 
    public abstract void contextDestroyed(javax.servlet.ServletContextEvent arg0);
}
再关注ContextLoaderListener类的关键代码:
public class ContextLoaderListener extends ContextLoader implements ServletContextListener{
    private ContextLoader contextLoader;

    public void contextInitialized(ServletContextEvent event)
    {
        this.contextLoader.initWebApplicationContext(event.getServletContext());
    }
}
public class ContextLoader{
    private WebApplicationContext context;

    public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
    {
        ApplicationContext parent = loadParentContext(servletContext);
        this.context = createWebApplicationContext(servletContext, parent);
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    }

    protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent)
    {
        ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
        wac.setParent(parent);
        wac.setServletContext(sc);
        wac.setConfigLocation(sc.getInitParameter("contextConfigLocation"));
        return wac;
    }

}
可以发现,配置了ContextLoaderListener类后,在应用启动时应用会回调ContextLoader.initWebApplicationContext((ServletContext )方法创建WebApplicationContext 对象,即Spring容器。创建过程中还会调用ServletContext.getInitParameter("contextConfigLocation")方法读取contextConfigLocation初始化参数。我们还可以发现,Spring容器创建成功后还被放到了ServletContext中。

 

当使用Spring容器管理Struts2的Action时,由于每个Action对应一次用户请求,且封装了该次请求的状态信息,所以不应将Action配置成单例模式,因此必须指定scope属性,该属性值可指定为prototype和request两种。

 

Spring提供的HibernateTemplate和HibernateCallback互为补充,HibernateTemplate对通用操作进行封装,HibernateCallback弥补了封装后不能访问Hibernate API这个灵活性不足的缺陷。
private List<?> findByPage(final String hql, final Object[] paramValues, final int firstResult, final int maxResults){
    return ht.executeFind(new HibernateCallback(){
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            Query query = session.createQuery(hql);
            for(int i = 0; i < paramValues.length; i++){
                query.setParameter(i, paramValues[i]);
            }
            return query.setFirstResult(firstResult).setMaxResults(maxResults).list();
        }
    });
}
@SuppressWarnings("unchecked")
public List<Product> findProductByPage(int firstResult, int maxResults){
    String hql = "from Product p";
    return (List<Product>)findByPage(hql, null, firstResult, maxResults);
}

 

equals()方法可如下方式写:
public boolean equals(Object obj){
 if(this == obj){
  return true;
 }
 if(obj != null && this.getClass() == obj.getClass()){
  Employee emp = (Employee)obj;
  return this.getName().equals(emp.getName()) && this.getPassword().equals(emp.getPassword());
 }
 return false;
}
不要根据标识属性重写equals()和hashCode()方法,因为持久化对象处于瞬态时,这些对象的标识属性值可能是null。


静态include与动态include区别:

静态include:<%@ include file="test.jsp"%>

动态include:<jsp:include page="test.jsp">

静态include是将被导入页面的代码与包含页面的代码融合成一个jsp页面,然后将这个jsp页面解析成一个Servlet;

动态include则是将两个jsp页面分别解析成Servlet,然后在包含jsp对应的Servlet中调用被包含页面对应的Servlet。


http GET请求与POSt请求的区别:

1)get请求是指直接通过浏览器访问某个url,或者通过表单提交,且method属性为空或者属性值为get;post请求是指通过表单提交,且method的属性值为post;

2)GET方式提交的数据会在地址栏中显示出来,而POST提交则不会,它放在请求体里,所以post请求的安全性更高;

3)虽然http协议没有对url的长度和传输数据大小进行限制,但浏览器、服务器或操作系统往往会对其进行限制,而且通过post方式提交的数据往往比get方式提交的数据更大。


转发(forward)与重定向(redirect)的区别:

转发后依然是同一次请求,共享同一个request,所以地址栏不会发生变化,在目标页面还可以访问到原request的参数;

重定向向服务器重新发送了第二次请求,request发生了变化,所以地址栏会变成新url,在目标页面访问不到原request的参数。


cookie与session的区别:

Cookie通常用于在用户的浏览器端保存某些信息,如登录用户名、密码或页面个性化设置等信息,这样用户下次进入同一个网站时可以不用重新登录,并可以个性化显示用户的页面等。cookie若设置了生存期限,它里面的信息会一直保存在用户的浏览器端,直到超出其生存期限;若没有设置生存期限,它里面的信息会随着浏览器的关闭而被清除;

Session代表一次用户会话,所谓的“一次用户会话”即从客户端浏览器连接服务器开始到断开为止。Session通常用于在服务器端保存用户的会话信息,比如判断用户是否登录,或者获取购物车中的商品信息等,session里的信息会随着浏览器的关闭而清除。










原创粉丝点击