在salesforce中$component可以理解为跟要找的节点的共同的祖先,
Archive for the ‘Computers and Internet’ Category
$Component Leave a comment
Haversine Formula Leave a comment
deploy from sandbox to production Leave a comment
Change Sets, Force.com IDE, ANT, unmanaged package, managed package.
chatter user guide 101 Leave a comment
salesforce code example Leave a comment
log4j使用DailyRollingFileAppender Leave a comment
原文链接:http://www.wenhq.com/article/view_420.html
DailyRollingFileAppender是日志记录软件包Log4J中的一个Appender,它能够按一定的频度滚动日志记录文件。
log4j.appender.S.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}-%m%n
在DailyRollingFileAppender中可以指定monthly(每月)、weekly(每周)、daily(每天)、half-daily(每半天)、hourly(每小时)和minutely(每分钟)六个频度,这是通过为 DatePattern选项赋予不同的值来完成的。DatePattern选项的有效值为:
* ‘.’yyyy-MM,对应monthly(每月)
* ‘.’yyyy-ww,对应weekly(每周)
* ‘.’yyyy-MM-dd,对应daily(每天)
* ‘.’yyyy-MM-dd-a,对应half-daily(每半天)
* ‘.’yyyy-MM-dd-HH,对应hourly(每小时)
* ‘.’yyyy-MM-dd-HH-mm,对应minutely(每分钟)
log4j.additivity 是 子Logger 是否继承父Logger 的 输出源(appender)的标志位。具体说,默认情况下,子Logger 会继承父Logger 的appender,也就是说 子Logger 会在父Logger 的appender里输出。若是additivity设为false,则子Logger 只会在自己的appender里输出,而不会在父Logger 的appender里输出。
log4j.rootCategory=info,console
log4j.logger.abc.log4jTest=debug,console
log4j.additivity.abc.log4jTest=false
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
其中abc为包名,log4jTest为类名,log4j.logger为固定的,不能改变!!
基本的格式为:
for root Logger
log4j.rootLogger=[priority], appenderName, apenderName, ….
for Appender
log4j.appender.appenderName=fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1=value1
…
log4j.appender.appenderName.option1=value1
Logger组件的继承关系有以下特点:
- 如果子类Logger组件没有定义日志级别,则将继承父类的日志级别
- 如果子类Logger组件定义了日志级别,就不会继承父类的日志级别
- 在默认情况下,子类Logger组件会继承父类的所有Appender,把他们加入到自己的Appender清单中。
- 如果把子类的Logger组件的additivity标志设为false,那么它就不会继承父类的Appender. addiivity标志的默认值是true.
例子:
log4j.rootLogger=INFO,console
日志级别=INFO
appender清单=console
log4j.apache.helloappLogger=WARN
日志级别=WARN
appender清单=console(继承)
log4j.apache.helloappLogger.childLogger=,file
日志级别=WARN(继承)
appender清单=console(继承),file
Difference between WhoId & WhatId on Task Leave a comment
WhoID refers to people things. So that would be typically a Lead ID or a Contact ID
WhatID refers to object type things. That would typically be an Account ID or an Opportunity ID
Tasks and Events have two fields (whoId and whatId) that can reference multiple object types … whoId => Lead|Account, whatId => Account|Asset|Campaign|Case…
inner and outter join Leave a comment
http://stackoverflow.com/questions/38549/sql-difference-between-inner-and-outer-join
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
Cascade Insert with External Id Fields Leave a comment
http://blogs.developerforce.com/engineering/2012/02/cascade-insert-with-external-id-fields.html
The problem
If you’re like me, you’ve got a whole bunch of external data in the form of Grandparent -> Parent -> Child. Those are all one-to-many relationships. You’d like to import this data into Salesforce — into three corresponding custom objects, in fact. You’d like to represent those relationships with with some master-detail fields, and you’d really like to be economical with your insert statements because you live in mortal terror of governor limits.
The useless solution
The naive method of accomplishing this is about as attractive as a centipede with pox. Insert the Grandparent row, by itself. Retrieve the id, and use it to populate Parent__c.Grandparent__c. Insert all the parents, retrieve the ids, and then use those ids to populate Child__c.Parent__c. In a world where an insert call can process up to 200 records at a time, wasting an insert on a single record is a reprehensible offense. Also, this approach must be done synchronously, and that’s not such a great option when you’re talking about tens of thousands of records.
The much better solution
Let’s talk about external ids for a second. You can read up on them here, but the basic gist is that you can create a custom field on an object in Salesforce and set it to be an external id (and if you do this, you probably also want to set it to require unique values). Setting the external id attribute tells Salesforce that this field is used as an identifier in some other, non-Salesforce system. This lets you do some extremely powerful things, like call upsert on a whole bunch of data without Salesforce ids.
It also lets you denote foreign key relationships. So even if I don’t know the Salesforce id of my Grandparent, I can do something like this:
Grandparent__c g = new Grandparent__c();
g.External_Id__c = ‘myExtId’;
Parent__c parent = new Parent__c();
parent.Grandparent__r = g;
insert(parent);
See that? I don’t need the id of the Grandparent object. I just need its external id. When I insert the parent into Salesforce, the foreign key to Grandparent will be populated with the correct Grandparent row. Pretty neat, huh?
Note the __r on the foreign key field in the example. That suffix denotes a relationship field which can be populated by an object, rather than a normal __c vield which takes a single value.
The last piece of the cascade insert puzzle is something I’m going to call mixed save, because I don’t think it has an official name (hello, marketing!). Mixed save is a feature of our API that allows you to include multiple types of objects in an insert or update call (but not upsert!). So let’s look at that last example again. For that to work, the Grandparent row already has to exist in Salesforce, right?
Maybe not.
Grandparent__c g = new Grandparent__c();
g.name = ‘gp’;
g.External_Id__c = ‘myExtId’;
Grandparent__c nestedObject = new Grandparent__c();
nestedObject.External_Id__c = ‘myExtId’;
Parent__c parent = new Parent__c();
parent.Grandparent__r = nestedObject;
insert([g, parent]);
Pay special attention to the nestedObject record above. It represents the same data record as g and yet we’re creating a separate object. This is necessary. It’s tempting to say parent.Grandparent__r = g; but it won’t work. Trust me. I spent hours on this so that you don’t have to. You can find more information on mixed save by scrolling down to the “Creating Records for Different Object Types” section of this page.
Well that’s pretty neat. I’m inserting a record and its child at the same time in the same DML call and Salesforce will automatically fill in the right foreign key values. So now, going back to my original problem, I can create some external id fields on my Grandparent__c and Parent__c objects, make sure the corresponding fields are populated in my existing data, split everything into batches of 200, and insert to my heart’s content.
SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结 Leave a comment
http://jinnianshilongnian.iteye.com/blog/1423971
下载地址
一 开发环境
1、动态web工程
2、部分依赖
3、为了方便学习,暂没有使用maven构建工程
二 工程主要包括内容
1、springMVC + spring3.1.1 + hibernate4.1.0集成
2、通用DAO层 和 Service层
3、二级缓存 Ehcache
4、REST风格的表现层
5、通用分页(两个版本)
5.1、首页 上一页,下一页 尾页 跳转
5.2、上一页 1 2 3 4 5 下一页
6、数据库连接池采用proxool
7、spring集成测试
8、表现层的 java validator框架验证(采用hibernate-validator-4.2.0实现)
9、视图采用JSP,并进行组件化分离
三 TODO LIST 将本项目做成脚手架方便以后新项目查询
1、Service层进行AOP缓存(缓存使用Memcached实现)
2、单元测试(把常见的桩测试、伪实现、模拟对象演示一遍 区别集成测试)
3、监控功能
后台查询hibernate二级缓存 hit/miss率功能
后台查询当前服务器状态功能(如 线程信息、服务器相关信息)
4、spring RPC功能
5、spring集成 quartz 进行任务调度
6、spring集成 java mail进行邮件发送
7、DAO层将各种常用框架集成进来(方便查询)
8、把工作中经常用的东西 融合进去,作为脚手架,方便以后查询
四 集成重点及常见问题
1、spring-config.xml 配置文件:
1.1、该配置文件只加载除表现层之外的所有bean,因此需要如下配置:
通过exclude-filter 把所有 @Controller注解的表现层控制器组件排除
1.2、国际化消息文件配置
- <!– 国际化的消息资源文件 –>
- <bean id=”messageSource” class=”org.springframework.context.support.ReloadableResourceBundleMessageSource”>
- <property name=”basenames”>
- <list>
- <!– 在web环境中一定要定位到classpath 否则默认到当前web应用下找 –>
- <value>classpath:messages</value>
- </list>
- </property>
- <property name=”defaultEncoding” value=”UTF-8″/>
- <property name=”cacheSeconds” value=”60″/>
- </bean>
此处basenames内一定是 classpath:messages ,如果你写出“messages”,将会到你的web应用的根下找 即你的messages.properties一定在 web应用/messages.propertis。
1.3、hibernate的sessionFactory配置 需要使用org.springframework.orm.hibernate4.LocalSessionFactoryBean,其他都是类似的,具体看源代码。
1.4、<aop:aspectj-autoproxy expose-proxy=”true”/> 实现@AspectJ注解的,默认使用AnnotationAwareAspectJAutoProxyCreator进行AOP代理,它是 BeanPostProcessor的子类,在容器启动时Bean初始化开始和结束时调用进行AOP代理的创建,因此只对当容器启动时有效,使用时注意此 处。
1.5、声明式容器管理事务
建议使用声明式容器管理事务,而不建议使用注解容器管理事务(虽然简单),但太分布式了,采用声明式容器管理事务一般只对service层进行处理。
- <tx:advice id=”txAdvice” transaction-manager=”txManager”>
- <tx:attributes>
- <tx:method name=”save*” propagation=”REQUIRED” />
- <tx:method name=”add*” propagation=”REQUIRED” />
- <tx:method name=”create*” propagation=”REQUIRED” />
- <tx:method name=”insert*” propagation=”REQUIRED” />
- <tx:method name=”update*” propagation=”REQUIRED” />
- <tx:method name=”merge*” propagation=”REQUIRED” />
- <tx:method name=”del*” propagation=”REQUIRED” />
- <tx:method name=”remove*” propagation=”REQUIRED” />
- <tx:method name=”put*” propagation=”REQUIRED” />
- <tx:method name=”use*” propagation=”REQUIRED”/>
- <!–hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到–>
- <tx:method name=”get*” propagation=”REQUIRED” read-only=”true” />
- <tx:method name=”count*” propagation=”REQUIRED” read-only=”true” />
- <tx:method name=”find*” propagation=”REQUIRED” read-only=”true” />
- <tx:method name=”list*” propagation=”REQUIRED” read-only=”true” />
- <tx:method name=”*” read-only=”true” />
- </tx:attributes>
- </tx:advice>
- <aop:config expose-proxy=”true”>
- <!– 只对业务逻辑层实施事务 –>
- <aop:pointcut id=”txPointcut” expression=”execution(* cn.javass..service..*.*(..))” />
- <aop:advisor advice-ref=”txAdvice” pointcut-ref=”txPointcut”/>
- </aop:config>
此处一定注意 使用 hibernate4,在不使用OpenSessionInView模式时,在使用getCurrentSession()时会有如下问题:
当有一个方法list 传播行为为Supports,当在另一个方法getPage()(无事务)调用list方法时会抛出 org.hibernate.HibernateException: No Session found for current thread 异常。
这是因为getCurrentSession()在没有session的情况下不会自动创建一个,不知道这是不是Spring3.1实现的bug,欢迎大家讨论下。
因此最好的解决方案是使用REQUIRED的传播行为。
二、spring-servlet.xml:
2.1、表现层配置文件,只应加装表现层Bean,否则可能引起问题。
此处只应该加载表现层组件,如果此处还加载dao层或service层的bean会将之前容器加载的替换掉,而且此处不会进行AOP织入,所以会造成AOP失效问题(如事务不起作用),再回头看我们的1.4讨论的。
2.2、<mvc:view-controller path=“/” view-name=“forward:/index”/> 表示当访问主页时自动转发到index控制器。
2.3、静态资源映射
- <!– 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 –>
- <mvc:default-servlet-handler/>
- <!– 静态资源映射 –>
- <mvc:resources mapping=”/images/**” location=”/WEB-INF/images/” />
- <mvc:resources mapping=”/css/**” location=”/WEB-INF/css/” />
- <mvc:resources mapping=”/js/**” location=”/WEB-INF/js/” />
以上是配置文件部分,接下来来看具体代码。
三、通用DAO层Hibernate4实现
为了减少各模块实现的代码量,实际工作时都会有通用DAO层实现,以下是部分核心代码:
- public abstract class BaseHibernateDao<M extends java.io.Serializable, PK extends java.io.Serializable> implements IBaseDao<M, PK> {
- protected static final Logger LOGGER = LoggerFactory.getLogger(BaseHibernateDao.class);
- private final Class<M> entityClass;
- private final String HQL_LIST_ALL;
- private final String HQL_COUNT_ALL;
- private final String HQL_OPTIMIZE_PRE_LIST_ALL;
- private final String HQL_OPTIMIZE_NEXT_LIST_ALL;
- private String pkName = null;
- @SuppressWarnings(“unchecked”)
- public BaseHibernateDao() {
- this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
- Field[] fields = this.entityClass.getDeclaredFields();
- for(Field f : fields) {
- if(f.isAnnotationPresent(Id.class)) {
- this.pkName = f.getName();
- }
- }
- Assert.notNull(pkName);
- //TODO @Entity name not null
- HQL_LIST_ALL = “from ” + this.entityClass.getSimpleName() + ” order by ” + pkName + ” desc”;
- HQL_OPTIMIZE_PRE_LIST_ALL = “from ” + this.entityClass.getSimpleName() + ” where ” + pkName + ” > ? order by ” + pkName + ” asc”;
- HQL_OPTIMIZE_NEXT_LIST_ALL = “from ” + this.entityClass.getSimpleName() + ” where ” + pkName + ” < ? order by ” + pkName + ” desc”;
- HQL_COUNT_ALL = ” select count(*) from ” + this.entityClass.getSimpleName();
- }
- @Autowired
- @Qualifier(“sessionFactory”)
- private SessionFactory sessionFactory;
- public Session getSession() {
- //事务必须是开启的,否则获取不到
- return sessionFactory.getCurrentSession();
- }
- ……
- }
Spring3.1集成Hibernate4不再需要HibernateDaoSupport和HibernateTemplate了,直接使用原生API即可。
四、通用Service层代码 此处省略,看源代码,有了通用代码后CURD就不用再写了。
- @Service(“UserService”)
- public class UserServiceImpl extends BaseService<UserModel, Integer> implements UserService {
- private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
- private UserDao userDao;
- @Autowired
- @Qualifier(“UserDao”)
- @Override
- public void setBaseDao(IBaseDao<UserModel, Integer> userDao) {
- this.baseDao = userDao;
- this.userDao = (UserDao) userDao;
- }
- @Override
- public Page<UserModel> query(int pn, int pageSize, UserQueryModel command) {
- return PageUtil.getPage(userDao.countQuery(command) ,pn, userDao.query(pn, pageSize, command), pageSize);
- }
- }
五、表现层 Controller实现
采用SpringMVC支持的REST风格实现,具体看代码,此处我们使用了java Validator框架 来进行 表现层数据验证
在Model实现上加验证注解
- @Pattern(regexp = “[A-Za-z0-9]{5,20}”, message = “{username.illegal}”) //java validator验证(用户名字母数字组成,长度为5-10)
- private String username;
- @NotEmpty(message = “{email.illegal}”)
- @Email(message = “{email.illegal}”) //错误消息会自动到MessageSource中查找
- private String email;
- @Pattern(regexp = “[A-Za-z0-9]{5,20}”, message = “{password.illegal}”)
- private String password;
- @DateFormat( message=”{register.date.error}”)//自定义的验证器
- private Date registerDate;
在Controller中相应方法的需要验证的参数上加@Valid即可
六、Spring集成测试
使用Spring集成测试能很方便的进行Bean的测试,而且使用 @TransactionConfiguration(transactionManager = “txManager”, defaultRollback = true)能自动回滚事务,清理测试前后状态。
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = {“classpath:spring-config.xml”})
- @Transactional
- @TransactionConfiguration(transactionManager = “txManager”, defaultRollback = true)
- public class UserServiceTest {
- AtomicInteger counter = new AtomicInteger();
- @Autowired
- private UserService userService;
- ……
- }
其他部分请直接看源码,欢迎大家讨论。