发表于: 2018-03-24 23:46:25

1 570


今天完成的事情:(一定要写非常细致的内容,比如说学会了盒子模型,了解了Margin) 

一、关于如何获得当前时间戳及如何转化为标准时间

1.时间戳:在计算机中,「时间戳」一般是指 Unix 时间戳,即自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。

在Java中可以使用System.currentTimeMillis()/1000,因为前面的方法获得的是从1970.1.1.0.0.0到目前的毫秒数,一般使用long类型储存

2.可以在程序中将其转化为标准时间

//获得当前时间的时间戳(毫秒)
long currentTime=System.currentTimeMillis();
//转化为当前标准时间
Date date=new Date(currentTime);
//设置输出的时间格式
SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
//调用格式化方法将当前标准时间转化为想要的输出格式输出
System.out.println(format.format(date));


3.在原有表格中添加created_at和updated_at属性,并且设置为根据当前时间自动改变时间戳,

create_time 设置 CURRENT_TIMESTAMP属性

update_time 设置 ON UPDATE CURRENT_TIMESTAMP属性

 会发现报错

错误是因为mysql5.60之前的版本中不允许同时出现两个current_time,所以只能将第一个设置为current_time,第二个不指定默认值,而是采用触发器的形式来触发。

因为任务一中要求其数据类型为bigint,所以先暂时不用这种方法。而是直接采用Bigint类型然后在添加数据时将当前时间戳赋予给created_at属性,在更新数据时将当前时间戳赋予给给updated_at属性

4.首先,修改Person类

public class Person{
private int id;
private String name ;
private int age ;
private String personID ;
private Long created_at;
private Long updated_at;

//其他省略了
public Long getCreated_at() {
return created_at;
}
public void setCreated_at(Long created_at){
this.created_at=created_at;
}
public Long getUpdated_at(){
return updated_at;
}
public void setUpdated_at(Long updated_at){
this.updated_at=updated_at;
}

public String toString() {
return "Person{"+"id="+id+",name="+name+",age="+age+",personID="+personID+"}";
}
}

修改Mapper.xml,因为如果不修改,是无法在java中输入此属性到数据库的

在addPerson中加入created_at

<insert id="addPerson" parameterType="Person" useGeneratedKeys="true" keyProperty="id" >
insert into person1 (created_at,name,age,personID) values (#{created_at},#{name},#{age},#{personID})
</insert>

在updatePerson中加入updated_at

<update id="updatePerson" parameterType="Person" >
update person1
<set>
<if test="name!=null">name=#{name},</if>
<if test="age!=null">age=#{age},</if>
<if test="personID!=null">personID=#{personID},</if><!--注意逗号不能丢-->
<if test="updated_at!=null">updated_at=#{updated_at}</if>
</set>
where id=#{id}
</update>

再在PersonServiceImpl中将当前时间储存进去

public class PersonServiceImpl implements PersonService {
private ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
private IPersonDao personDao = ctx.getBean(IPersonDao.class);

public List<Person> addAndList(Person person, Map map) {
//增加插入时间
       person.setCreated_at(System.currentTimeMillis());
personDao.addPerson(person);
List<Person> list = personDao.listPerson(map);
return list;
}
//其余无改动方法省略
public List<Person> updateAndList(Person person, Map map) {
//增加修改时间
       person.setUpdated_at(System.currentTimeMillis());
personDao.updatePerson(person);
List<Person> list = personDao.listPerson(map);
return list;
}

public int justAdd(Person person) {
//增加插入时间
       person.setCreated_at(System.currentTimeMillis());
personDao.addPerson(person);
return person.getId();
}

public Boolean justUpdate(Person person) {
//增加更新时间
       person.setUpdated_at(System.currentTimeMillis());
return   personDao.updatePerson(person);
}
}

Main方法

public class Main {
public static void main(String[] args)throws Exception {
       PersonService ps = new PersonServiceImpl();
Person p = new Person("wangdada", 25, "20111");
ps.justAdd(p);
}
}

可以看到虽然不是系统自动更新时间,但是通过在Impl中将设置时间放进了添加数据和更新数据的方法中,再调用此方法时就可以实现伪自动更新时间了,不过在test测试类里还是要自己手动插入的,插入时注意思考代码顺序,因为是将时间属性先放进person对象中,再将对象插入到数据库,所以不能没对象时就设置时间也不能插入结束再设置时间。

@Test
public void justAdd() {
Person p1=new Person("zhangsan",25,"2015");
p1.setCreated_at(System.currentTimeMillis());
personDao.addPerson(p1);

System.out.println( "插入成功,新插入对象id为:"+p1.getId());
}
@Test
public void justUpdate() {

Person p1=new Person(23056,"libababab",28,"2011111");
p1.setUpdated_at(System.currentTimeMillis());
personDao.updatePerson(p1);

}

可以看到,因为service层的存在,所以可以实现只要一个接口方法就能插入数据的同时插入创建时间, 其实,将创建时间和更新时间看成是Person类的一个特殊属性即可,其他的属性都是很直观的,可以直接读和看出来的,然而这个属性却是需要我们用系统自带的方法即时获得的,所以在构造方法中如果直接将这两个加进去,然后创建对象的时候直接使用System.currentTimeMillis()将其填在属性中应该也是可以跳过set方法,直接录入此属性。

public Person(Long created_at,String name, int age, String personID) {
this.created_at=created_at;
this.name = name;
this.age = age;
this.personID = personID;
}
@Test
public void justAdd() {
Person p1=new Person(System.currentTimeMillis(),"zhangsan",25,"2015");
//直接利用构造方法填入更新时间
personDao.addPerson(p1);
System.out.println( "插入成功,新插入对象id为:"+p1.getId());
}

此时,为了方便起见,可以将原先的两种有参构造删除,这样强制规定只能在new时就将需要的当前时间填上去即可。这样的话,不用service层也可以实现带时间的增改了。

二、log4j之前就了解过并且配置了文件,结合这几天用的情况回顾一下

1.需要知道其输出级别是分为5类,从低到高依次为DEBUG-INFO-WARN-ERROR-FATAL,一般情况下设置为INFO,因为DEBUG的话实在是太多了。。。

2.Apperder为日志输出地,Log4j提供的Apperder包括以下几种

org.apache.log4j.ConsoleAppender(控制台),一般为必选,可以在跑程序时就看见信息
org.apache.log4j.FileAppender(文件),一般不推荐
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),一般使用比较多因为方便查询
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),一般也不推荐
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方),没了解过

3.Layout为日志输出格式,Log4j提供的Layout有以下几种

org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),最常用,因为可以按照自己的要求来灵活改变输出形式
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

4.再上一遍配置文件

### 设置###
log4j.rootLogger = info,stdout,D,E

### 输出信息到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出Info级别以上的日志到=F://logs/info.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = F://logs/info.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG  
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=F://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =F://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

可以看到我是设置了最低显示级别为Info,因为之前设置了Debug级别发现每次运行程序那个debug晃得眼都要瞎了,半天就有2MB的内存文件,所以。。。

配置文件中有三个输出场所,分别是控制台输出所有Info及以上信息,Info.log文件储存所有Info及以上信息,Error.log文件储存所有Error及以上信息,做个小实验,在Main函数中先创建一个logger对象,然后调用三个输出方法

public static void main(String[] args)throws Exception {
Logger logger=Logger.getLogger(Main.class);
//这里注意选择logger的包
   logger.debug("这是一条debug语句");
logger.info("这是一条info语句");

logger.error("这是一条error语句,小心哦");

}

结果如图

可以看到,因为我设置了级别,所以第一句debug的语句并没有显示出来,而另外两句话则不仅在控制台显示出来了,更是在记事本中储存了起来。那么对于一些我们需要存储的数据,我们就可以不用System.out.prinln来输出,而是使用logger.info(),这样不仅可以在控制台输出,还可以保存到文档中,方便日后查看。至于哪些需要记录,就看情况需要了,比如在try-catch中捕捉到了Expection,就可以输出到Error信息中。而测试类中就不需要存储了,因为毕竟测试类的目的就是测试程序的运行的。

三、主键归零

当进行大批量测试插入,更新,删除等步骤后,主键由于其自增和唯一性,会变得断断续续,并且很大,此时就可以使用清空表格并且主键归零的方法,

当表中数据都不需要时,可以使用truncate table tablename;

当只想删除不需要主键归零时,可以使用delete from tablename;

当只想主键归零不想删除数据时,可以使用dbcc checkident (’table_name’, reseed, new_reseed_value);不过不适用于Mysql,适合sqlServer

所以可以在Mapper.xml中增加一个truncate方法来清空表格和主键

<update id="truncatePerson">
truncate table person1
</update>
Boolean truncatePerson();//PersonDao
Boolean truncatePerson();//PersonService
public Boolean truncatePerson() {
return personDao.truncatePerson();
}

但是在主程序中运行时会有小bug,就是明明清空了表格返回值却是false

四、Debug调试

1.idea与eclipse的不同点在于,eclipse可以直接在程序编写界面的左侧设置断点,而idea是要进入debug调试界面之后才可以进行设置断点。

2.shift+F9或者点击小虫子按钮进入调试页面,

3.在程序编辑页面左侧插入断点,

4.ctrl+shift+f8可以查看所有断点情况

5.在断点详情页面可以将断点设置为条件断点,

条件断点,即当运行时条件为true时,才会进入断点。在断点详情窗口左侧选中要设置的断点,然后在右侧的Condition:选项上打勾,并在输入框中写上表达式,如图所示。

删除断点:在左侧选中断点,并点上方的红色减号即可删除。

6.当程序运行到断点处,就可以看到此处所有变量的值

7.在断点处执行表达式:在断点所示在代码行,单击右键,选择Evaluate Expression...或按快捷键Alt+F8,打开表达式执行窗口,在窗口处输入表达式并回车,在下方可以看到表达式的值。

8.当需要继续向下运行时,点击下方DEBUG窗口上的工具栏上的调试按钮,可以实现下一步,进入方法,返回方法等操作,当不想继续断点调试时,点击左则的绿色三角形按钮,即可恢复程序运行。

①step over:程序向下执行一行(如果当前行有方法调用,这个方法将被执行完毕返回,然后到下一行)

②step into:程序向下执行一行。如果该行有自定义方法,则运行进入自定义方法(不会进入官方类库的方法)。

③force step into:该按钮在调试的时候能进入任何方法。

④step out:如果在调试的时候你进入了一个方法,并觉得该方法没有问题,你就可以使用stepout跳出该方法,返回到该方法被调用处的下一行语句。值得注意的是,该方法已执行完毕。

⑤drop frame:点击该按钮后,你将返回到当前方法的调用处重新执行,并且所有上下文变量的值也回到那个时候。只要调用链中还有上级方法,可以跳到其中的任何一个方法。

⑥resume program:在多个断点间直接移动,会跳过断点间数据


明天计划的事情:(一定要写非常细致的内容) 

感觉将代码再完善一下可以做task22,用远程服务器来跑单元测试了


遇到的问题:(遇到什么困难,怎么解决的)

1.在设置cerated_at时间时,遇到因为Mysql版本问题不能使用两个带currentstamp的stamp,所以想用触发器来解决,无奈搞了好几次都没成功,所以放弃了

2.关于truncate方法为甚恶魔成功后返回值为false没太搞明白,不过这个没什么意义。

收获:(通过今天的学习,学到了什么知识)

1.学会了怎么在增加和更新时将创建时间和更新时间自动添加进去

2.详细回顾了log4j的配置及用法

3.掌握了主键归零操作

4.初步了解了怎么在idea中进行debug调错,以后还要多练习

5.代码还是需要再规范一些


返回列表 返回列表
评论

    分享到