建表代码如下:
create table Y_Data(
Id int PRIMARY key auto_increment,
Position VARCHAR(200) not null DEFAULT '',
CorporateName VARCHAR(500) not null DEFAULT '',
WorkingPlace VARCHAR(1000) not NULL DEFAULT '',
Salary VARCHAR(200) not null DEFAULT '',
ReleaseTime VARCHAR(300) not null DEFAULT '',
DataTime timestamp not NULL default CURRENT_TIMESTAMP
)
插入时,不指定DataTime的值,则会默认使用系统时间值。
如果指定???
insert into person(id,name,age)
values
(#{user.id}, #{user.name}, #{user.age})
以上代码的效果相当于
insert into person(id,name,age) values (1,'kai',20),(2,'lvbu',20),...;
//注意在MySQL中,sql语句有长度限制,默认大小为1M
//可以找到my.ini文件(window系统下),my.conf(Linux系统下),
//在配置里面加入max_allowed_packet=64M,可以把长度限制修改为64M
1)pom文件中导入依赖
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapper-spring-boot-starterartifactId>
<version>2.1.5version>
dependency>
2)创建一个BaseMapper类
import tk.mybatis.mapper.common.ConditionMapper;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
public interface BaseMapper<T> extends Mapper<T>, MySqlMapper<T>, ConditionMapper<T> {
}
3)要使用的Mapper接口继承BaseMapper接口
import tk.mybatis.mapper.common.BaseMapper;
public interface PersonMapper extends BaseMapper{
}
4)PersonMapper 的实例直接调用insertList(List list)方法
personMapper.insertList(list);
insert ignore into person(id,name,age) values (1,'kai',20),(2,'lvbu',20) ;
//insert ignore into:如果表中有主键约束或者唯一(联合)索引约束,在插入数据时,
//如果主键或唯一索引存在了,就不会在插入后面这条数据
upsert=update or insert
MySQL中使用on duplicate key update实现:
//原始写法
insert into person04(id,name,age) values (1,'kai',20),(2,'lvbu',20)
on duplicate key update
id=values(id),
name=values(name),
age=values(age);
insert into WC_OIL_GAS_T(period,rebate_type,custom_code,entity_code)
values
(#{user.period},#{user.rebate_type},#{user.custom_code},#{user.entity_code})
on duplicate key update
period=values(period),
rebate_type=values(rebate_type),
custom_code=values(custom_code),
entity_code=values(entity_code)
//WC_OIL_GAS_T表中有一个update_date字段,
//`UPDATE_DATE` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间'
//即设置为系统时间,在第一次单纯插入数据时,即使不指定这个字段的值,会使用当时插入
//时的系统时间,而在upsert时,如果已经存在了该主键或者唯一索引,且没指定update_date
//的更新后的值,那么不会更新update_date,如果指定了呢?
如果指定了update_date的值,就会更新:
insert into WC_OIL_GAS_T(period,rebate_type,custom_code,entity_code,update_date)
values
(#{user.period},#{user.rebate_type},#{user.custom_code},#{user.entity_code},now())
on duplicate key update
period=values(period),
rebate_type=values(rebate_type),
custom_code=values(custom_code),
entity_code=values(entity_code),
update_date=values(update_date)
//这里使用now()更新update_date字段,和MySQL默认系统时间格式相同
//如 "2019-08-15 10:14:39"
问题:json字符串中的key值为全大写,javaBean的属性名与之对应(也全大写)
//将json对应的String --> 对象
XXXObjest obj= JSONObject.parseObject(after,XXXObjest .class);
//解析不了,会报错,用Google的Gson可以解析,但是不建议
//因为如果javaBean的属性名全大写,mybatis端用不了
解决:将key值全转为小写,javaBean的属性名与之对应(也全小写)
//转换方法 由于该json字符串结构简单,k:v,k:v,... 所以采用以下方法
public class JUtil02 {
public static void main(String[] args) {
String before = "{\"NAME\":\"2017\",\"PERIOD\":\"001\",\"age\":17}";
JSONObject parseObj = JSON.parseObject(before);
JSONObject afterObj = new JSONObject();
for(Map.Entry<String,Object> entry:parseObj.entrySet()){
afterObj.put(entry.getKey().toLowerCase(),entry.getValue());
}
String after=afterObj.toJSONString();
System.out.println(after);
}
}
public class MyTimeUtil {
/**
* @param timeStr "Jun 27, 2019 3:36:16 PM"
* @return
*/
public static String TimeFormat(String timeStr){
SimpleDateFormat sdf = new SimpleDateFormat ("MMM dd, yyyy h:mm:ss a", Locale.UK);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format1="";
try
{
//"Jun 27, 2019 3:36:16 PM" -->"Thu Jun 27 15:36:16 CST 2019"
Date parse = sdf.parse(timeStr);
System.out.println (sdf.parse (timeStr));
//"Thu Jun 27 15:36:16 CST 2019"-->"2019-06-27 15:36:16"
format1 = format.format(parse);
System.out.println(format1);
}
catch (ParseException e)
{
e.printStackTrace();
}
return format1;
}
}
json字符串中某些key对应的value值为’null’,解析为javaBean中的属性时,其值为null(空),插入到MySQL中的字段值为null(空)
mysql | java |
---|---|
varchar | String |
decimal | BigDecimal |
timestamp | Timestamp |
decimal(15,4)表示的是最大可达15位(包含小数),小数四位,
java用java.math.BigDecimal (或double)就可以
show create table tb_name
//2者等效
desc tb_name;
show columns from tb_name;
//COMMENT 关键字
CREATE TABLE tb_name(
id VARCHAR(30) COMMENT '用户ID',
name VARCHAR(30) COMMENT '用户名称'
)
Kerberos ???
Kerberos 是一种网络认证协议,其设计目标是通过密钥系统为客户机 / 服务器应用程序提供强大的认证服务。
1.文件准备:krb5.conf,jaas.conf,username.keytab
krb5.conf的存放路径:
windows -> c:\windows\krb5.ini
linux -> /etc/krb5.conf
2.在jaas.conf文件中需指定username.keytab文件的绝对路径
3.在hosts文件中配置Kafka服务器的地址映射:
//即使代码中用ip指定Kafka的服务器,也必须配置hosts
C:\Windows\System32\drivers\etc
// 这个地方填写放kafka_krb5.conf的路径 windows server环境下后缀用.ini linux环境下后缀用.conf
System.setProperty("java.security.krb5.conf","c:\\windows\\krb5.ini");
// 这个地方填写放kafka_jass.conf的路径
System.setProperty("java.security.auth.login.config","c:\\windows\\jaas.ini");//jaas.ini
Properties props = new Properties();
//消费的主题所在的服务器 地址:端口
props.put("bootstrap.servers", "kafka-1:9090,kafka-2:9090,kafka-3:9090,kafka-4:9090");
props.put("acks", "1");
//组织id
props.put("group.id", "test");
// props.put("auto.offset.reset","earliest");//重置偏移量,需将组织id+1
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("key.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.kerberos.service.name", "kafka");
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(
props);
//消费的主题名
consumer.subscribe(Arrays.asList("topic_name"));
System.out.println("登录成功连接__WC_OIL_GAS_T");
注意:
1.jaas.conf和krb5.conf文件的路径可以在虚拟机参数中设置
Java启动参数(JVM参数): //参数就之间空格隔开
-Djava.security.auth.login.config=/path/jaas.conf //jaas文件路径
-Djava.security.krb5.conf=/path/krb5.conf //krb5.conf文件路径
//重置偏移量,需将组织id+1
props.put("group.id", "test");//组织id+1
props.put("auto.offset.reset","earliest");//重置偏移量
/* 读取数据,读取超时时间为100ms */
ConsumerRecords<String, String> records = consumer.poll(100);
//遍历kafka记录
for (ConsumerRecord<String, String> record : records) {
//records.count() 可以返回 某次读取的数据条数
}
问题:数量少于应取数量
原因:每次限制了批量插入的数据为100条,不足100条时的判断条件有误
解决:每取到一批数据,由于数据量不会很大,直接一次全部插入
在多线程时使用@Autowired总是获取不到bean,原因是:new thread不在spring
容器中,也就无法获得spring中的bean对象。
解决方法:手动获取
解决方案
/**
*核心代码如下
*/
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
//用于在线程中获取mapper对象
@Component
public class BeanContext implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
BeanContext.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T)applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
return (T)applicationContext.getBean(clz);
}
}
原文:https://blog.csdn.net/u011493599/article/details/78522315